diff options
Diffstat (limited to 'fs')
101 files changed, 5551 insertions, 2463 deletions
diff --git a/fs/Kconfig b/fs/Kconfig index c0022b1d5877..86b203fc3c56 100644 --- a/fs/Kconfig +++ b/fs/Kconfig | |||
@@ -176,6 +176,8 @@ source "fs/romfs/Kconfig" | |||
176 | source "fs/sysv/Kconfig" | 176 | source "fs/sysv/Kconfig" |
177 | source "fs/ufs/Kconfig" | 177 | source "fs/ufs/Kconfig" |
178 | 178 | ||
179 | source "fs/exofs/Kconfig" | ||
180 | |||
179 | endif # MISC_FILESYSTEMS | 181 | endif # MISC_FILESYSTEMS |
180 | 182 | ||
181 | menuconfig NETWORK_FILESYSTEMS | 183 | menuconfig NETWORK_FILESYSTEMS |
diff --git a/fs/Makefile b/fs/Makefile index 055d5237b109..70b2aed87133 100644 --- a/fs/Makefile +++ b/fs/Makefile | |||
@@ -122,3 +122,4 @@ obj-$(CONFIG_DEBUG_FS) += debugfs/ | |||
122 | obj-$(CONFIG_OCFS2_FS) += ocfs2/ | 122 | obj-$(CONFIG_OCFS2_FS) += ocfs2/ |
123 | obj-$(CONFIG_BTRFS_FS) += btrfs/ | 123 | obj-$(CONFIG_BTRFS_FS) += btrfs/ |
124 | obj-$(CONFIG_GFS2_FS) += gfs2/ | 124 | obj-$(CONFIG_GFS2_FS) += gfs2/ |
125 | obj-$(CONFIG_EXOFS_FS) += exofs/ | ||
diff --git a/fs/compat_ioctl.c b/fs/compat_ioctl.c index ff786687e93b..3e87ce443ea2 100644 --- a/fs/compat_ioctl.c +++ b/fs/compat_ioctl.c | |||
@@ -23,7 +23,7 @@ | |||
23 | #include <linux/if.h> | 23 | #include <linux/if.h> |
24 | #include <linux/if_bridge.h> | 24 | #include <linux/if_bridge.h> |
25 | #include <linux/slab.h> | 25 | #include <linux/slab.h> |
26 | #include <linux/raid/md.h> | 26 | #include <linux/raid/md_u.h> |
27 | #include <linux/kd.h> | 27 | #include <linux/kd.h> |
28 | #include <linux/route.h> | 28 | #include <linux/route.h> |
29 | #include <linux/in6.h> | 29 | #include <linux/in6.h> |
diff --git a/fs/exofs/BUGS b/fs/exofs/BUGS new file mode 100644 index 000000000000..1b2d4c63a579 --- /dev/null +++ b/fs/exofs/BUGS | |||
@@ -0,0 +1,3 @@ | |||
1 | - Out-of-space may cause a severe problem if the object (and directory entry) | ||
2 | were written, but the inode attributes failed. Then if the filesystem was | ||
3 | unmounted and mounted the kernel can get into an endless loop doing a readdir. | ||
diff --git a/fs/exofs/Kbuild b/fs/exofs/Kbuild new file mode 100644 index 000000000000..cc2d22db119c --- /dev/null +++ b/fs/exofs/Kbuild | |||
@@ -0,0 +1,16 @@ | |||
1 | # | ||
2 | # Kbuild for the EXOFS module | ||
3 | # | ||
4 | # Copyright (C) 2008 Panasas Inc. All rights reserved. | ||
5 | # | ||
6 | # Authors: | ||
7 | # Boaz Harrosh <bharrosh@panasas.com> | ||
8 | # | ||
9 | # This program is free software; you can redistribute it and/or modify | ||
10 | # it under the terms of the GNU General Public License version 2 | ||
11 | # | ||
12 | # Kbuild - Gets included from the Kernels Makefile and build system | ||
13 | # | ||
14 | |||
15 | exofs-y := osd.o inode.o file.o symlink.o namei.o dir.o super.o | ||
16 | obj-$(CONFIG_EXOFS_FS) += exofs.o | ||
diff --git a/fs/exofs/Kconfig b/fs/exofs/Kconfig new file mode 100644 index 000000000000..86194b2f799d --- /dev/null +++ b/fs/exofs/Kconfig | |||
@@ -0,0 +1,13 @@ | |||
1 | config EXOFS_FS | ||
2 | tristate "exofs: OSD based file system support" | ||
3 | depends on SCSI_OSD_ULD | ||
4 | help | ||
5 | EXOFS is a file system that uses an OSD storage device, | ||
6 | as its backing storage. | ||
7 | |||
8 | # Debugging-related stuff | ||
9 | config EXOFS_DEBUG | ||
10 | bool "Enable debugging" | ||
11 | depends on EXOFS_FS | ||
12 | help | ||
13 | This option enables EXOFS debug prints. | ||
diff --git a/fs/exofs/common.h b/fs/exofs/common.h new file mode 100644 index 000000000000..b1512c4bb8c7 --- /dev/null +++ b/fs/exofs/common.h | |||
@@ -0,0 +1,184 @@ | |||
1 | /* | ||
2 | * common.h - Common definitions for both Kernel and user-mode utilities | ||
3 | * | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
6 | * Copyright (C) 2005, 2006 | ||
7 | * International Business Machines | ||
8 | * Copyright (C) 2008, 2009 | ||
9 | * Boaz Harrosh <bharrosh@panasas.com> | ||
10 | * | ||
11 | * Copyrights for code taken from ext2: | ||
12 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
13 | * Remy Card (card@masi.ibp.fr) | ||
14 | * Laboratoire MASI - Institut Blaise Pascal | ||
15 | * Universite Pierre et Marie Curie (Paris VI) | ||
16 | * from | ||
17 | * linux/fs/minix/inode.c | ||
18 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
19 | * | ||
20 | * This file is part of exofs. | ||
21 | * | ||
22 | * exofs is free software; you can redistribute it and/or modify | ||
23 | * it under the terms of the GNU General Public License as published by | ||
24 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
25 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
26 | * version of GPL for exofs is version 2. | ||
27 | * | ||
28 | * exofs is distributed in the hope that it will be useful, | ||
29 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
30 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
31 | * GNU General Public License for more details. | ||
32 | * | ||
33 | * You should have received a copy of the GNU General Public License | ||
34 | * along with exofs; if not, write to the Free Software | ||
35 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
36 | */ | ||
37 | |||
38 | #ifndef __EXOFS_COM_H__ | ||
39 | #define __EXOFS_COM_H__ | ||
40 | |||
41 | #include <linux/types.h> | ||
42 | |||
43 | #include <scsi/osd_attributes.h> | ||
44 | #include <scsi/osd_initiator.h> | ||
45 | #include <scsi/osd_sec.h> | ||
46 | |||
47 | /**************************************************************************** | ||
48 | * Object ID related defines | ||
49 | * NOTE: inode# = object ID - EXOFS_OBJ_OFF | ||
50 | ****************************************************************************/ | ||
51 | #define EXOFS_MIN_PID 0x10000 /* Smallest partition ID */ | ||
52 | #define EXOFS_OBJ_OFF 0x10000 /* offset for objects */ | ||
53 | #define EXOFS_SUPER_ID 0x10000 /* object ID for on-disk superblock */ | ||
54 | #define EXOFS_ROOT_ID 0x10002 /* object ID for root directory */ | ||
55 | |||
56 | /* exofs Application specific page/attribute */ | ||
57 | # define EXOFS_APAGE_FS_DATA (OSD_APAGE_APP_DEFINED_FIRST + 3) | ||
58 | # define EXOFS_ATTR_INODE_DATA 1 | ||
59 | |||
60 | /* | ||
61 | * The maximum number of files we can have is limited by the size of the | ||
62 | * inode number. This is the largest object ID that the file system supports. | ||
63 | * Object IDs 0, 1, and 2 are always in use (see above defines). | ||
64 | */ | ||
65 | enum { | ||
66 | EXOFS_MAX_INO_ID = (sizeof(ino_t) * 8 == 64) ? ULLONG_MAX : | ||
67 | (1ULL << (sizeof(ino_t) * 8ULL - 1ULL)), | ||
68 | EXOFS_MAX_ID = (EXOFS_MAX_INO_ID - 1 - EXOFS_OBJ_OFF), | ||
69 | }; | ||
70 | |||
71 | /**************************************************************************** | ||
72 | * Misc. | ||
73 | ****************************************************************************/ | ||
74 | #define EXOFS_BLKSHIFT 12 | ||
75 | #define EXOFS_BLKSIZE (1UL << EXOFS_BLKSHIFT) | ||
76 | |||
77 | /**************************************************************************** | ||
78 | * superblock-related things | ||
79 | ****************************************************************************/ | ||
80 | #define EXOFS_SUPER_MAGIC 0x5DF5 | ||
81 | |||
82 | /* | ||
83 | * The file system control block - stored in an object's data (mainly, the one | ||
84 | * with ID EXOFS_SUPER_ID). This is where the in-memory superblock is stored | ||
85 | * on disk. Right now it just has a magic value, which is basically a sanity | ||
86 | * check on our ability to communicate with the object store. | ||
87 | */ | ||
88 | struct exofs_fscb { | ||
89 | __le64 s_nextid; /* Highest object ID used */ | ||
90 | __le32 s_numfiles; /* Number of files on fs */ | ||
91 | __le16 s_magic; /* Magic signature */ | ||
92 | __le16 s_newfs; /* Non-zero if this is a new fs */ | ||
93 | }; | ||
94 | |||
95 | /**************************************************************************** | ||
96 | * inode-related things | ||
97 | ****************************************************************************/ | ||
98 | #define EXOFS_IDATA 5 | ||
99 | |||
100 | /* | ||
101 | * The file control block - stored in an object's attributes. This is where | ||
102 | * the in-memory inode is stored on disk. | ||
103 | */ | ||
104 | struct exofs_fcb { | ||
105 | __le64 i_size; /* Size of the file */ | ||
106 | __le16 i_mode; /* File mode */ | ||
107 | __le16 i_links_count; /* Links count */ | ||
108 | __le32 i_uid; /* Owner Uid */ | ||
109 | __le32 i_gid; /* Group Id */ | ||
110 | __le32 i_atime; /* Access time */ | ||
111 | __le32 i_ctime; /* Creation time */ | ||
112 | __le32 i_mtime; /* Modification time */ | ||
113 | __le32 i_flags; /* File flags (unused for now)*/ | ||
114 | __le32 i_generation; /* File version (for NFS) */ | ||
115 | __le32 i_data[EXOFS_IDATA]; /* Short symlink names and device #s */ | ||
116 | }; | ||
117 | |||
118 | #define EXOFS_INO_ATTR_SIZE sizeof(struct exofs_fcb) | ||
119 | |||
120 | /* This is the Attribute the fcb is stored in */ | ||
121 | static const struct __weak osd_attr g_attr_inode_data = ATTR_DEF( | ||
122 | EXOFS_APAGE_FS_DATA, | ||
123 | EXOFS_ATTR_INODE_DATA, | ||
124 | EXOFS_INO_ATTR_SIZE); | ||
125 | |||
126 | /**************************************************************************** | ||
127 | * dentry-related things | ||
128 | ****************************************************************************/ | ||
129 | #define EXOFS_NAME_LEN 255 | ||
130 | |||
131 | /* | ||
132 | * The on-disk directory entry | ||
133 | */ | ||
134 | struct exofs_dir_entry { | ||
135 | __le64 inode_no; /* inode number */ | ||
136 | __le16 rec_len; /* directory entry length */ | ||
137 | u8 name_len; /* name length */ | ||
138 | u8 file_type; /* umm...file type */ | ||
139 | char name[EXOFS_NAME_LEN]; /* file name */ | ||
140 | }; | ||
141 | |||
142 | enum { | ||
143 | EXOFS_FT_UNKNOWN, | ||
144 | EXOFS_FT_REG_FILE, | ||
145 | EXOFS_FT_DIR, | ||
146 | EXOFS_FT_CHRDEV, | ||
147 | EXOFS_FT_BLKDEV, | ||
148 | EXOFS_FT_FIFO, | ||
149 | EXOFS_FT_SOCK, | ||
150 | EXOFS_FT_SYMLINK, | ||
151 | EXOFS_FT_MAX | ||
152 | }; | ||
153 | |||
154 | #define EXOFS_DIR_PAD 4 | ||
155 | #define EXOFS_DIR_ROUND (EXOFS_DIR_PAD - 1) | ||
156 | #define EXOFS_DIR_REC_LEN(name_len) \ | ||
157 | (((name_len) + offsetof(struct exofs_dir_entry, name) + \ | ||
158 | EXOFS_DIR_ROUND) & ~EXOFS_DIR_ROUND) | ||
159 | |||
160 | /************************* | ||
161 | * function declarations * | ||
162 | *************************/ | ||
163 | /* osd.c */ | ||
164 | void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], | ||
165 | const struct osd_obj_id *obj); | ||
166 | |||
167 | int exofs_check_ok_resid(struct osd_request *or, u64 *in_resid, u64 *out_resid); | ||
168 | static inline int exofs_check_ok(struct osd_request *or) | ||
169 | { | ||
170 | return exofs_check_ok_resid(or, NULL, NULL); | ||
171 | } | ||
172 | int exofs_sync_op(struct osd_request *or, int timeout, u8 *cred); | ||
173 | int exofs_async_op(struct osd_request *or, | ||
174 | osd_req_done_fn *async_done, void *caller_context, u8 *cred); | ||
175 | |||
176 | int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr); | ||
177 | |||
178 | int osd_req_read_kern(struct osd_request *or, | ||
179 | const struct osd_obj_id *obj, u64 offset, void *buff, u64 len); | ||
180 | |||
181 | int osd_req_write_kern(struct osd_request *or, | ||
182 | const struct osd_obj_id *obj, u64 offset, void *buff, u64 len); | ||
183 | |||
184 | #endif /*ifndef __EXOFS_COM_H__*/ | ||
diff --git a/fs/exofs/dir.c b/fs/exofs/dir.c new file mode 100644 index 000000000000..65b0c8c776a1 --- /dev/null +++ b/fs/exofs/dir.c | |||
@@ -0,0 +1,672 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include "exofs.h" | ||
37 | |||
38 | static inline unsigned exofs_chunk_size(struct inode *inode) | ||
39 | { | ||
40 | return inode->i_sb->s_blocksize; | ||
41 | } | ||
42 | |||
43 | static inline void exofs_put_page(struct page *page) | ||
44 | { | ||
45 | kunmap(page); | ||
46 | page_cache_release(page); | ||
47 | } | ||
48 | |||
49 | /* Accesses dir's inode->i_size must be called under inode lock */ | ||
50 | static inline unsigned long dir_pages(struct inode *inode) | ||
51 | { | ||
52 | return (inode->i_size + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT; | ||
53 | } | ||
54 | |||
55 | static unsigned exofs_last_byte(struct inode *inode, unsigned long page_nr) | ||
56 | { | ||
57 | loff_t last_byte = inode->i_size; | ||
58 | |||
59 | last_byte -= page_nr << PAGE_CACHE_SHIFT; | ||
60 | if (last_byte > PAGE_CACHE_SIZE) | ||
61 | last_byte = PAGE_CACHE_SIZE; | ||
62 | return last_byte; | ||
63 | } | ||
64 | |||
65 | static int exofs_commit_chunk(struct page *page, loff_t pos, unsigned len) | ||
66 | { | ||
67 | struct address_space *mapping = page->mapping; | ||
68 | struct inode *dir = mapping->host; | ||
69 | int err = 0; | ||
70 | |||
71 | dir->i_version++; | ||
72 | |||
73 | if (!PageUptodate(page)) | ||
74 | SetPageUptodate(page); | ||
75 | |||
76 | if (pos+len > dir->i_size) { | ||
77 | i_size_write(dir, pos+len); | ||
78 | mark_inode_dirty(dir); | ||
79 | } | ||
80 | set_page_dirty(page); | ||
81 | |||
82 | if (IS_DIRSYNC(dir)) | ||
83 | err = write_one_page(page, 1); | ||
84 | else | ||
85 | unlock_page(page); | ||
86 | |||
87 | return err; | ||
88 | } | ||
89 | |||
90 | static void exofs_check_page(struct page *page) | ||
91 | { | ||
92 | struct inode *dir = page->mapping->host; | ||
93 | unsigned chunk_size = exofs_chunk_size(dir); | ||
94 | char *kaddr = page_address(page); | ||
95 | unsigned offs, rec_len; | ||
96 | unsigned limit = PAGE_CACHE_SIZE; | ||
97 | struct exofs_dir_entry *p; | ||
98 | char *error; | ||
99 | |||
100 | /* if the page is the last one in the directory */ | ||
101 | if ((dir->i_size >> PAGE_CACHE_SHIFT) == page->index) { | ||
102 | limit = dir->i_size & ~PAGE_CACHE_MASK; | ||
103 | if (limit & (chunk_size - 1)) | ||
104 | goto Ebadsize; | ||
105 | if (!limit) | ||
106 | goto out; | ||
107 | } | ||
108 | for (offs = 0; offs <= limit - EXOFS_DIR_REC_LEN(1); offs += rec_len) { | ||
109 | p = (struct exofs_dir_entry *)(kaddr + offs); | ||
110 | rec_len = le16_to_cpu(p->rec_len); | ||
111 | |||
112 | if (rec_len < EXOFS_DIR_REC_LEN(1)) | ||
113 | goto Eshort; | ||
114 | if (rec_len & 3) | ||
115 | goto Ealign; | ||
116 | if (rec_len < EXOFS_DIR_REC_LEN(p->name_len)) | ||
117 | goto Enamelen; | ||
118 | if (((offs + rec_len - 1) ^ offs) & ~(chunk_size-1)) | ||
119 | goto Espan; | ||
120 | } | ||
121 | if (offs != limit) | ||
122 | goto Eend; | ||
123 | out: | ||
124 | SetPageChecked(page); | ||
125 | return; | ||
126 | |||
127 | Ebadsize: | ||
128 | EXOFS_ERR("ERROR [exofs_check_page]: " | ||
129 | "size of directory #%lu is not a multiple of chunk size", | ||
130 | dir->i_ino | ||
131 | ); | ||
132 | goto fail; | ||
133 | Eshort: | ||
134 | error = "rec_len is smaller than minimal"; | ||
135 | goto bad_entry; | ||
136 | Ealign: | ||
137 | error = "unaligned directory entry"; | ||
138 | goto bad_entry; | ||
139 | Enamelen: | ||
140 | error = "rec_len is too small for name_len"; | ||
141 | goto bad_entry; | ||
142 | Espan: | ||
143 | error = "directory entry across blocks"; | ||
144 | goto bad_entry; | ||
145 | bad_entry: | ||
146 | EXOFS_ERR( | ||
147 | "ERROR [exofs_check_page]: bad entry in directory #%lu: %s - " | ||
148 | "offset=%lu, inode=%llu, rec_len=%d, name_len=%d", | ||
149 | dir->i_ino, error, (page->index<<PAGE_CACHE_SHIFT)+offs, | ||
150 | _LLU(le64_to_cpu(p->inode_no)), | ||
151 | rec_len, p->name_len); | ||
152 | goto fail; | ||
153 | Eend: | ||
154 | p = (struct exofs_dir_entry *)(kaddr + offs); | ||
155 | EXOFS_ERR("ERROR [exofs_check_page]: " | ||
156 | "entry in directory #%lu spans the page boundary" | ||
157 | "offset=%lu, inode=%llu", | ||
158 | dir->i_ino, (page->index<<PAGE_CACHE_SHIFT)+offs, | ||
159 | _LLU(le64_to_cpu(p->inode_no))); | ||
160 | fail: | ||
161 | SetPageChecked(page); | ||
162 | SetPageError(page); | ||
163 | } | ||
164 | |||
165 | static struct page *exofs_get_page(struct inode *dir, unsigned long n) | ||
166 | { | ||
167 | struct address_space *mapping = dir->i_mapping; | ||
168 | struct page *page = read_mapping_page(mapping, n, NULL); | ||
169 | |||
170 | if (!IS_ERR(page)) { | ||
171 | kmap(page); | ||
172 | if (!PageChecked(page)) | ||
173 | exofs_check_page(page); | ||
174 | if (PageError(page)) | ||
175 | goto fail; | ||
176 | } | ||
177 | return page; | ||
178 | |||
179 | fail: | ||
180 | exofs_put_page(page); | ||
181 | return ERR_PTR(-EIO); | ||
182 | } | ||
183 | |||
184 | static inline int exofs_match(int len, const unsigned char *name, | ||
185 | struct exofs_dir_entry *de) | ||
186 | { | ||
187 | if (len != de->name_len) | ||
188 | return 0; | ||
189 | if (!de->inode_no) | ||
190 | return 0; | ||
191 | return !memcmp(name, de->name, len); | ||
192 | } | ||
193 | |||
194 | static inline | ||
195 | struct exofs_dir_entry *exofs_next_entry(struct exofs_dir_entry *p) | ||
196 | { | ||
197 | return (struct exofs_dir_entry *)((char *)p + le16_to_cpu(p->rec_len)); | ||
198 | } | ||
199 | |||
200 | static inline unsigned | ||
201 | exofs_validate_entry(char *base, unsigned offset, unsigned mask) | ||
202 | { | ||
203 | struct exofs_dir_entry *de = (struct exofs_dir_entry *)(base + offset); | ||
204 | struct exofs_dir_entry *p = | ||
205 | (struct exofs_dir_entry *)(base + (offset&mask)); | ||
206 | while ((char *)p < (char *)de) { | ||
207 | if (p->rec_len == 0) | ||
208 | break; | ||
209 | p = exofs_next_entry(p); | ||
210 | } | ||
211 | return (char *)p - base; | ||
212 | } | ||
213 | |||
214 | static unsigned char exofs_filetype_table[EXOFS_FT_MAX] = { | ||
215 | [EXOFS_FT_UNKNOWN] = DT_UNKNOWN, | ||
216 | [EXOFS_FT_REG_FILE] = DT_REG, | ||
217 | [EXOFS_FT_DIR] = DT_DIR, | ||
218 | [EXOFS_FT_CHRDEV] = DT_CHR, | ||
219 | [EXOFS_FT_BLKDEV] = DT_BLK, | ||
220 | [EXOFS_FT_FIFO] = DT_FIFO, | ||
221 | [EXOFS_FT_SOCK] = DT_SOCK, | ||
222 | [EXOFS_FT_SYMLINK] = DT_LNK, | ||
223 | }; | ||
224 | |||
225 | #define S_SHIFT 12 | ||
226 | static unsigned char exofs_type_by_mode[S_IFMT >> S_SHIFT] = { | ||
227 | [S_IFREG >> S_SHIFT] = EXOFS_FT_REG_FILE, | ||
228 | [S_IFDIR >> S_SHIFT] = EXOFS_FT_DIR, | ||
229 | [S_IFCHR >> S_SHIFT] = EXOFS_FT_CHRDEV, | ||
230 | [S_IFBLK >> S_SHIFT] = EXOFS_FT_BLKDEV, | ||
231 | [S_IFIFO >> S_SHIFT] = EXOFS_FT_FIFO, | ||
232 | [S_IFSOCK >> S_SHIFT] = EXOFS_FT_SOCK, | ||
233 | [S_IFLNK >> S_SHIFT] = EXOFS_FT_SYMLINK, | ||
234 | }; | ||
235 | |||
236 | static inline | ||
237 | void exofs_set_de_type(struct exofs_dir_entry *de, struct inode *inode) | ||
238 | { | ||
239 | mode_t mode = inode->i_mode; | ||
240 | de->file_type = exofs_type_by_mode[(mode & S_IFMT) >> S_SHIFT]; | ||
241 | } | ||
242 | |||
243 | static int | ||
244 | exofs_readdir(struct file *filp, void *dirent, filldir_t filldir) | ||
245 | { | ||
246 | loff_t pos = filp->f_pos; | ||
247 | struct inode *inode = filp->f_path.dentry->d_inode; | ||
248 | unsigned int offset = pos & ~PAGE_CACHE_MASK; | ||
249 | unsigned long n = pos >> PAGE_CACHE_SHIFT; | ||
250 | unsigned long npages = dir_pages(inode); | ||
251 | unsigned chunk_mask = ~(exofs_chunk_size(inode)-1); | ||
252 | unsigned char *types = NULL; | ||
253 | int need_revalidate = (filp->f_version != inode->i_version); | ||
254 | |||
255 | if (pos > inode->i_size - EXOFS_DIR_REC_LEN(1)) | ||
256 | return 0; | ||
257 | |||
258 | types = exofs_filetype_table; | ||
259 | |||
260 | for ( ; n < npages; n++, offset = 0) { | ||
261 | char *kaddr, *limit; | ||
262 | struct exofs_dir_entry *de; | ||
263 | struct page *page = exofs_get_page(inode, n); | ||
264 | |||
265 | if (IS_ERR(page)) { | ||
266 | EXOFS_ERR("ERROR: " | ||
267 | "bad page in #%lu", | ||
268 | inode->i_ino); | ||
269 | filp->f_pos += PAGE_CACHE_SIZE - offset; | ||
270 | return PTR_ERR(page); | ||
271 | } | ||
272 | kaddr = page_address(page); | ||
273 | if (unlikely(need_revalidate)) { | ||
274 | if (offset) { | ||
275 | offset = exofs_validate_entry(kaddr, offset, | ||
276 | chunk_mask); | ||
277 | filp->f_pos = (n<<PAGE_CACHE_SHIFT) + offset; | ||
278 | } | ||
279 | filp->f_version = inode->i_version; | ||
280 | need_revalidate = 0; | ||
281 | } | ||
282 | de = (struct exofs_dir_entry *)(kaddr + offset); | ||
283 | limit = kaddr + exofs_last_byte(inode, n) - | ||
284 | EXOFS_DIR_REC_LEN(1); | ||
285 | for (; (char *)de <= limit; de = exofs_next_entry(de)) { | ||
286 | if (de->rec_len == 0) { | ||
287 | EXOFS_ERR("ERROR: " | ||
288 | "zero-length directory entry"); | ||
289 | exofs_put_page(page); | ||
290 | return -EIO; | ||
291 | } | ||
292 | if (de->inode_no) { | ||
293 | int over; | ||
294 | unsigned char d_type = DT_UNKNOWN; | ||
295 | |||
296 | if (types && de->file_type < EXOFS_FT_MAX) | ||
297 | d_type = types[de->file_type]; | ||
298 | |||
299 | offset = (char *)de - kaddr; | ||
300 | over = filldir(dirent, de->name, de->name_len, | ||
301 | (n<<PAGE_CACHE_SHIFT) | offset, | ||
302 | le64_to_cpu(de->inode_no), | ||
303 | d_type); | ||
304 | if (over) { | ||
305 | exofs_put_page(page); | ||
306 | return 0; | ||
307 | } | ||
308 | } | ||
309 | filp->f_pos += le16_to_cpu(de->rec_len); | ||
310 | } | ||
311 | exofs_put_page(page); | ||
312 | } | ||
313 | |||
314 | return 0; | ||
315 | } | ||
316 | |||
317 | struct exofs_dir_entry *exofs_find_entry(struct inode *dir, | ||
318 | struct dentry *dentry, struct page **res_page) | ||
319 | { | ||
320 | const unsigned char *name = dentry->d_name.name; | ||
321 | int namelen = dentry->d_name.len; | ||
322 | unsigned reclen = EXOFS_DIR_REC_LEN(namelen); | ||
323 | unsigned long start, n; | ||
324 | unsigned long npages = dir_pages(dir); | ||
325 | struct page *page = NULL; | ||
326 | struct exofs_i_info *oi = exofs_i(dir); | ||
327 | struct exofs_dir_entry *de; | ||
328 | |||
329 | if (npages == 0) | ||
330 | goto out; | ||
331 | |||
332 | *res_page = NULL; | ||
333 | |||
334 | start = oi->i_dir_start_lookup; | ||
335 | if (start >= npages) | ||
336 | start = 0; | ||
337 | n = start; | ||
338 | do { | ||
339 | char *kaddr; | ||
340 | page = exofs_get_page(dir, n); | ||
341 | if (!IS_ERR(page)) { | ||
342 | kaddr = page_address(page); | ||
343 | de = (struct exofs_dir_entry *) kaddr; | ||
344 | kaddr += exofs_last_byte(dir, n) - reclen; | ||
345 | while ((char *) de <= kaddr) { | ||
346 | if (de->rec_len == 0) { | ||
347 | EXOFS_ERR( | ||
348 | "ERROR: exofs_find_entry: " | ||
349 | "zero-length directory entry"); | ||
350 | exofs_put_page(page); | ||
351 | goto out; | ||
352 | } | ||
353 | if (exofs_match(namelen, name, de)) | ||
354 | goto found; | ||
355 | de = exofs_next_entry(de); | ||
356 | } | ||
357 | exofs_put_page(page); | ||
358 | } | ||
359 | if (++n >= npages) | ||
360 | n = 0; | ||
361 | } while (n != start); | ||
362 | out: | ||
363 | return NULL; | ||
364 | |||
365 | found: | ||
366 | *res_page = page; | ||
367 | oi->i_dir_start_lookup = n; | ||
368 | return de; | ||
369 | } | ||
370 | |||
371 | struct exofs_dir_entry *exofs_dotdot(struct inode *dir, struct page **p) | ||
372 | { | ||
373 | struct page *page = exofs_get_page(dir, 0); | ||
374 | struct exofs_dir_entry *de = NULL; | ||
375 | |||
376 | if (!IS_ERR(page)) { | ||
377 | de = exofs_next_entry( | ||
378 | (struct exofs_dir_entry *)page_address(page)); | ||
379 | *p = page; | ||
380 | } | ||
381 | return de; | ||
382 | } | ||
383 | |||
384 | ino_t exofs_parent_ino(struct dentry *child) | ||
385 | { | ||
386 | struct page *page; | ||
387 | struct exofs_dir_entry *de; | ||
388 | ino_t ino; | ||
389 | |||
390 | de = exofs_dotdot(child->d_inode, &page); | ||
391 | if (!de) | ||
392 | return 0; | ||
393 | |||
394 | ino = le64_to_cpu(de->inode_no); | ||
395 | exofs_put_page(page); | ||
396 | return ino; | ||
397 | } | ||
398 | |||
399 | ino_t exofs_inode_by_name(struct inode *dir, struct dentry *dentry) | ||
400 | { | ||
401 | ino_t res = 0; | ||
402 | struct exofs_dir_entry *de; | ||
403 | struct page *page; | ||
404 | |||
405 | de = exofs_find_entry(dir, dentry, &page); | ||
406 | if (de) { | ||
407 | res = le64_to_cpu(de->inode_no); | ||
408 | exofs_put_page(page); | ||
409 | } | ||
410 | return res; | ||
411 | } | ||
412 | |||
413 | int exofs_set_link(struct inode *dir, struct exofs_dir_entry *de, | ||
414 | struct page *page, struct inode *inode) | ||
415 | { | ||
416 | loff_t pos = page_offset(page) + | ||
417 | (char *) de - (char *) page_address(page); | ||
418 | unsigned len = le16_to_cpu(de->rec_len); | ||
419 | int err; | ||
420 | |||
421 | lock_page(page); | ||
422 | err = exofs_write_begin(NULL, page->mapping, pos, len, | ||
423 | AOP_FLAG_UNINTERRUPTIBLE, &page, NULL); | ||
424 | if (err) | ||
425 | EXOFS_ERR("exofs_set_link: exofs_write_begin FAILD => %d\n", | ||
426 | err); | ||
427 | |||
428 | de->inode_no = cpu_to_le64(inode->i_ino); | ||
429 | exofs_set_de_type(de, inode); | ||
430 | if (likely(!err)) | ||
431 | err = exofs_commit_chunk(page, pos, len); | ||
432 | exofs_put_page(page); | ||
433 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
434 | mark_inode_dirty(dir); | ||
435 | return err; | ||
436 | } | ||
437 | |||
438 | int exofs_add_link(struct dentry *dentry, struct inode *inode) | ||
439 | { | ||
440 | struct inode *dir = dentry->d_parent->d_inode; | ||
441 | const unsigned char *name = dentry->d_name.name; | ||
442 | int namelen = dentry->d_name.len; | ||
443 | unsigned chunk_size = exofs_chunk_size(dir); | ||
444 | unsigned reclen = EXOFS_DIR_REC_LEN(namelen); | ||
445 | unsigned short rec_len, name_len; | ||
446 | struct page *page = NULL; | ||
447 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | ||
448 | struct exofs_dir_entry *de; | ||
449 | unsigned long npages = dir_pages(dir); | ||
450 | unsigned long n; | ||
451 | char *kaddr; | ||
452 | loff_t pos; | ||
453 | int err; | ||
454 | |||
455 | for (n = 0; n <= npages; n++) { | ||
456 | char *dir_end; | ||
457 | |||
458 | page = exofs_get_page(dir, n); | ||
459 | err = PTR_ERR(page); | ||
460 | if (IS_ERR(page)) | ||
461 | goto out; | ||
462 | lock_page(page); | ||
463 | kaddr = page_address(page); | ||
464 | dir_end = kaddr + exofs_last_byte(dir, n); | ||
465 | de = (struct exofs_dir_entry *)kaddr; | ||
466 | kaddr += PAGE_CACHE_SIZE - reclen; | ||
467 | while ((char *)de <= kaddr) { | ||
468 | if ((char *)de == dir_end) { | ||
469 | name_len = 0; | ||
470 | rec_len = chunk_size; | ||
471 | de->rec_len = cpu_to_le16(chunk_size); | ||
472 | de->inode_no = 0; | ||
473 | goto got_it; | ||
474 | } | ||
475 | if (de->rec_len == 0) { | ||
476 | EXOFS_ERR("ERROR: exofs_add_link: " | ||
477 | "zero-length directory entry"); | ||
478 | err = -EIO; | ||
479 | goto out_unlock; | ||
480 | } | ||
481 | err = -EEXIST; | ||
482 | if (exofs_match(namelen, name, de)) | ||
483 | goto out_unlock; | ||
484 | name_len = EXOFS_DIR_REC_LEN(de->name_len); | ||
485 | rec_len = le16_to_cpu(de->rec_len); | ||
486 | if (!de->inode_no && rec_len >= reclen) | ||
487 | goto got_it; | ||
488 | if (rec_len >= name_len + reclen) | ||
489 | goto got_it; | ||
490 | de = (struct exofs_dir_entry *) ((char *) de + rec_len); | ||
491 | } | ||
492 | unlock_page(page); | ||
493 | exofs_put_page(page); | ||
494 | } | ||
495 | |||
496 | EXOFS_ERR("exofs_add_link: BAD dentry=%p or inode=%p", dentry, inode); | ||
497 | return -EINVAL; | ||
498 | |||
499 | got_it: | ||
500 | pos = page_offset(page) + | ||
501 | (char *)de - (char *)page_address(page); | ||
502 | err = exofs_write_begin(NULL, page->mapping, pos, rec_len, 0, | ||
503 | &page, NULL); | ||
504 | if (err) | ||
505 | goto out_unlock; | ||
506 | if (de->inode_no) { | ||
507 | struct exofs_dir_entry *de1 = | ||
508 | (struct exofs_dir_entry *)((char *)de + name_len); | ||
509 | de1->rec_len = cpu_to_le16(rec_len - name_len); | ||
510 | de->rec_len = cpu_to_le16(name_len); | ||
511 | de = de1; | ||
512 | } | ||
513 | de->name_len = namelen; | ||
514 | memcpy(de->name, name, namelen); | ||
515 | de->inode_no = cpu_to_le64(inode->i_ino); | ||
516 | exofs_set_de_type(de, inode); | ||
517 | err = exofs_commit_chunk(page, pos, rec_len); | ||
518 | dir->i_mtime = dir->i_ctime = CURRENT_TIME; | ||
519 | mark_inode_dirty(dir); | ||
520 | sbi->s_numfiles++; | ||
521 | |||
522 | out_put: | ||
523 | exofs_put_page(page); | ||
524 | out: | ||
525 | return err; | ||
526 | out_unlock: | ||
527 | unlock_page(page); | ||
528 | goto out_put; | ||
529 | } | ||
530 | |||
531 | int exofs_delete_entry(struct exofs_dir_entry *dir, struct page *page) | ||
532 | { | ||
533 | struct address_space *mapping = page->mapping; | ||
534 | struct inode *inode = mapping->host; | ||
535 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | ||
536 | char *kaddr = page_address(page); | ||
537 | unsigned from = ((char *)dir - kaddr) & ~(exofs_chunk_size(inode)-1); | ||
538 | unsigned to = ((char *)dir - kaddr) + le16_to_cpu(dir->rec_len); | ||
539 | loff_t pos; | ||
540 | struct exofs_dir_entry *pde = NULL; | ||
541 | struct exofs_dir_entry *de = (struct exofs_dir_entry *) (kaddr + from); | ||
542 | int err; | ||
543 | |||
544 | while (de < dir) { | ||
545 | if (de->rec_len == 0) { | ||
546 | EXOFS_ERR("ERROR: exofs_delete_entry:" | ||
547 | "zero-length directory entry"); | ||
548 | err = -EIO; | ||
549 | goto out; | ||
550 | } | ||
551 | pde = de; | ||
552 | de = exofs_next_entry(de); | ||
553 | } | ||
554 | if (pde) | ||
555 | from = (char *)pde - (char *)page_address(page); | ||
556 | pos = page_offset(page) + from; | ||
557 | lock_page(page); | ||
558 | err = exofs_write_begin(NULL, page->mapping, pos, to - from, 0, | ||
559 | &page, NULL); | ||
560 | if (err) | ||
561 | EXOFS_ERR("exofs_delete_entry: exofs_write_begin FAILD => %d\n", | ||
562 | err); | ||
563 | if (pde) | ||
564 | pde->rec_len = cpu_to_le16(to - from); | ||
565 | dir->inode_no = 0; | ||
566 | if (likely(!err)) | ||
567 | err = exofs_commit_chunk(page, pos, to - from); | ||
568 | inode->i_ctime = inode->i_mtime = CURRENT_TIME; | ||
569 | mark_inode_dirty(inode); | ||
570 | sbi->s_numfiles--; | ||
571 | out: | ||
572 | exofs_put_page(page); | ||
573 | return err; | ||
574 | } | ||
575 | |||
576 | /* kept aligned on 4 bytes */ | ||
577 | #define THIS_DIR ".\0\0" | ||
578 | #define PARENT_DIR "..\0" | ||
579 | |||
580 | int exofs_make_empty(struct inode *inode, struct inode *parent) | ||
581 | { | ||
582 | struct address_space *mapping = inode->i_mapping; | ||
583 | struct page *page = grab_cache_page(mapping, 0); | ||
584 | unsigned chunk_size = exofs_chunk_size(inode); | ||
585 | struct exofs_dir_entry *de; | ||
586 | int err; | ||
587 | void *kaddr; | ||
588 | |||
589 | if (!page) | ||
590 | return -ENOMEM; | ||
591 | |||
592 | err = exofs_write_begin(NULL, page->mapping, 0, chunk_size, 0, | ||
593 | &page, NULL); | ||
594 | if (err) { | ||
595 | unlock_page(page); | ||
596 | goto fail; | ||
597 | } | ||
598 | |||
599 | kaddr = kmap_atomic(page, KM_USER0); | ||
600 | de = (struct exofs_dir_entry *)kaddr; | ||
601 | de->name_len = 1; | ||
602 | de->rec_len = cpu_to_le16(EXOFS_DIR_REC_LEN(1)); | ||
603 | memcpy(de->name, THIS_DIR, sizeof(THIS_DIR)); | ||
604 | de->inode_no = cpu_to_le64(inode->i_ino); | ||
605 | exofs_set_de_type(de, inode); | ||
606 | |||
607 | de = (struct exofs_dir_entry *)(kaddr + EXOFS_DIR_REC_LEN(1)); | ||
608 | de->name_len = 2; | ||
609 | de->rec_len = cpu_to_le16(chunk_size - EXOFS_DIR_REC_LEN(1)); | ||
610 | de->inode_no = cpu_to_le64(parent->i_ino); | ||
611 | memcpy(de->name, PARENT_DIR, sizeof(PARENT_DIR)); | ||
612 | exofs_set_de_type(de, inode); | ||
613 | kunmap_atomic(page, KM_USER0); | ||
614 | err = exofs_commit_chunk(page, 0, chunk_size); | ||
615 | fail: | ||
616 | page_cache_release(page); | ||
617 | return err; | ||
618 | } | ||
619 | |||
620 | int exofs_empty_dir(struct inode *inode) | ||
621 | { | ||
622 | struct page *page = NULL; | ||
623 | unsigned long i, npages = dir_pages(inode); | ||
624 | |||
625 | for (i = 0; i < npages; i++) { | ||
626 | char *kaddr; | ||
627 | struct exofs_dir_entry *de; | ||
628 | page = exofs_get_page(inode, i); | ||
629 | |||
630 | if (IS_ERR(page)) | ||
631 | continue; | ||
632 | |||
633 | kaddr = page_address(page); | ||
634 | de = (struct exofs_dir_entry *)kaddr; | ||
635 | kaddr += exofs_last_byte(inode, i) - EXOFS_DIR_REC_LEN(1); | ||
636 | |||
637 | while ((char *)de <= kaddr) { | ||
638 | if (de->rec_len == 0) { | ||
639 | EXOFS_ERR("ERROR: exofs_empty_dir: " | ||
640 | "zero-length directory entry" | ||
641 | "kaddr=%p, de=%p\n", kaddr, de); | ||
642 | goto not_empty; | ||
643 | } | ||
644 | if (de->inode_no != 0) { | ||
645 | /* check for . and .. */ | ||
646 | if (de->name[0] != '.') | ||
647 | goto not_empty; | ||
648 | if (de->name_len > 2) | ||
649 | goto not_empty; | ||
650 | if (de->name_len < 2) { | ||
651 | if (le64_to_cpu(de->inode_no) != | ||
652 | inode->i_ino) | ||
653 | goto not_empty; | ||
654 | } else if (de->name[1] != '.') | ||
655 | goto not_empty; | ||
656 | } | ||
657 | de = exofs_next_entry(de); | ||
658 | } | ||
659 | exofs_put_page(page); | ||
660 | } | ||
661 | return 1; | ||
662 | |||
663 | not_empty: | ||
664 | exofs_put_page(page); | ||
665 | return 0; | ||
666 | } | ||
667 | |||
668 | const struct file_operations exofs_dir_operations = { | ||
669 | .llseek = generic_file_llseek, | ||
670 | .read = generic_read_dir, | ||
671 | .readdir = exofs_readdir, | ||
672 | }; | ||
diff --git a/fs/exofs/exofs.h b/fs/exofs/exofs.h new file mode 100644 index 000000000000..0fd4c7859679 --- /dev/null +++ b/fs/exofs/exofs.h | |||
@@ -0,0 +1,180 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/fs.h> | ||
37 | #include <linux/time.h> | ||
38 | #include "common.h" | ||
39 | |||
40 | #ifndef __EXOFS_H__ | ||
41 | #define __EXOFS_H__ | ||
42 | |||
43 | #define EXOFS_ERR(fmt, a...) printk(KERN_ERR "exofs: " fmt, ##a) | ||
44 | |||
45 | #ifdef CONFIG_EXOFS_DEBUG | ||
46 | #define EXOFS_DBGMSG(fmt, a...) \ | ||
47 | printk(KERN_NOTICE "exofs @%s:%d: " fmt, __func__, __LINE__, ##a) | ||
48 | #else | ||
49 | #define EXOFS_DBGMSG(fmt, a...) \ | ||
50 | do { if (0) printk(fmt, ##a); } while (0) | ||
51 | #endif | ||
52 | |||
53 | /* u64 has problems with printk this will cast it to unsigned long long */ | ||
54 | #define _LLU(x) (unsigned long long)(x) | ||
55 | |||
56 | /* | ||
57 | * our extension to the in-memory superblock | ||
58 | */ | ||
59 | struct exofs_sb_info { | ||
60 | struct osd_dev *s_dev; /* returned by get_osd_dev */ | ||
61 | osd_id s_pid; /* partition ID of file system*/ | ||
62 | int s_timeout; /* timeout for OSD operations */ | ||
63 | uint64_t s_nextid; /* highest object ID used */ | ||
64 | uint32_t s_numfiles; /* number of files on fs */ | ||
65 | spinlock_t s_next_gen_lock; /* spinlock for gen # update */ | ||
66 | u32 s_next_generation; /* next gen # to use */ | ||
67 | atomic_t s_curr_pending; /* number of pending commands */ | ||
68 | uint8_t s_cred[OSD_CAP_LEN]; /* all-powerful credential */ | ||
69 | }; | ||
70 | |||
71 | /* | ||
72 | * our extension to the in-memory inode | ||
73 | */ | ||
74 | struct exofs_i_info { | ||
75 | unsigned long i_flags; /* various atomic flags */ | ||
76 | uint32_t i_data[EXOFS_IDATA];/*short symlink names and device #s*/ | ||
77 | uint32_t i_dir_start_lookup; /* which page to start lookup */ | ||
78 | wait_queue_head_t i_wq; /* wait queue for inode */ | ||
79 | uint64_t i_commit_size; /* the object's written length */ | ||
80 | uint8_t i_cred[OSD_CAP_LEN];/* all-powerful credential */ | ||
81 | struct inode vfs_inode; /* normal in-memory inode */ | ||
82 | }; | ||
83 | |||
84 | /* | ||
85 | * our inode flags | ||
86 | */ | ||
87 | #define OBJ_2BCREATED 0 /* object will be created soon*/ | ||
88 | #define OBJ_CREATED 1 /* object has been created on the osd*/ | ||
89 | |||
90 | static inline int obj_2bcreated(struct exofs_i_info *oi) | ||
91 | { | ||
92 | return test_bit(OBJ_2BCREATED, &oi->i_flags); | ||
93 | } | ||
94 | |||
95 | static inline void set_obj_2bcreated(struct exofs_i_info *oi) | ||
96 | { | ||
97 | set_bit(OBJ_2BCREATED, &oi->i_flags); | ||
98 | } | ||
99 | |||
100 | static inline int obj_created(struct exofs_i_info *oi) | ||
101 | { | ||
102 | return test_bit(OBJ_CREATED, &oi->i_flags); | ||
103 | } | ||
104 | |||
105 | static inline void set_obj_created(struct exofs_i_info *oi) | ||
106 | { | ||
107 | set_bit(OBJ_CREATED, &oi->i_flags); | ||
108 | } | ||
109 | |||
110 | int __exofs_wait_obj_created(struct exofs_i_info *oi); | ||
111 | static inline int wait_obj_created(struct exofs_i_info *oi) | ||
112 | { | ||
113 | if (likely(obj_created(oi))) | ||
114 | return 0; | ||
115 | |||
116 | return __exofs_wait_obj_created(oi); | ||
117 | } | ||
118 | |||
119 | /* | ||
120 | * get to our inode from the vfs inode | ||
121 | */ | ||
122 | static inline struct exofs_i_info *exofs_i(struct inode *inode) | ||
123 | { | ||
124 | return container_of(inode, struct exofs_i_info, vfs_inode); | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * Maximum count of links to a file | ||
129 | */ | ||
130 | #define EXOFS_LINK_MAX 32000 | ||
131 | |||
132 | /************************* | ||
133 | * function declarations * | ||
134 | *************************/ | ||
135 | /* inode.c */ | ||
136 | void exofs_truncate(struct inode *inode); | ||
137 | int exofs_setattr(struct dentry *, struct iattr *); | ||
138 | int exofs_write_begin(struct file *file, struct address_space *mapping, | ||
139 | loff_t pos, unsigned len, unsigned flags, | ||
140 | struct page **pagep, void **fsdata); | ||
141 | extern struct inode *exofs_iget(struct super_block *, unsigned long); | ||
142 | struct inode *exofs_new_inode(struct inode *, int); | ||
143 | extern int exofs_write_inode(struct inode *, int); | ||
144 | extern void exofs_delete_inode(struct inode *); | ||
145 | |||
146 | /* dir.c: */ | ||
147 | int exofs_add_link(struct dentry *, struct inode *); | ||
148 | ino_t exofs_inode_by_name(struct inode *, struct dentry *); | ||
149 | int exofs_delete_entry(struct exofs_dir_entry *, struct page *); | ||
150 | int exofs_make_empty(struct inode *, struct inode *); | ||
151 | struct exofs_dir_entry *exofs_find_entry(struct inode *, struct dentry *, | ||
152 | struct page **); | ||
153 | int exofs_empty_dir(struct inode *); | ||
154 | struct exofs_dir_entry *exofs_dotdot(struct inode *, struct page **); | ||
155 | ino_t exofs_parent_ino(struct dentry *child); | ||
156 | int exofs_set_link(struct inode *, struct exofs_dir_entry *, struct page *, | ||
157 | struct inode *); | ||
158 | |||
159 | /********************* | ||
160 | * operation vectors * | ||
161 | *********************/ | ||
162 | /* dir.c: */ | ||
163 | extern const struct file_operations exofs_dir_operations; | ||
164 | |||
165 | /* file.c */ | ||
166 | extern const struct inode_operations exofs_file_inode_operations; | ||
167 | extern const struct file_operations exofs_file_operations; | ||
168 | |||
169 | /* inode.c */ | ||
170 | extern const struct address_space_operations exofs_aops; | ||
171 | |||
172 | /* namei.c */ | ||
173 | extern const struct inode_operations exofs_dir_inode_operations; | ||
174 | extern const struct inode_operations exofs_special_inode_operations; | ||
175 | |||
176 | /* symlink.c */ | ||
177 | extern const struct inode_operations exofs_symlink_inode_operations; | ||
178 | extern const struct inode_operations exofs_fast_symlink_inode_operations; | ||
179 | |||
180 | #endif | ||
diff --git a/fs/exofs/file.c b/fs/exofs/file.c new file mode 100644 index 000000000000..6ed7fe484752 --- /dev/null +++ b/fs/exofs/file.c | |||
@@ -0,0 +1,87 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/buffer_head.h> | ||
37 | |||
38 | #include "exofs.h" | ||
39 | |||
40 | static int exofs_release_file(struct inode *inode, struct file *filp) | ||
41 | { | ||
42 | return 0; | ||
43 | } | ||
44 | |||
45 | static int exofs_file_fsync(struct file *filp, struct dentry *dentry, | ||
46 | int datasync) | ||
47 | { | ||
48 | int ret; | ||
49 | struct address_space *mapping = filp->f_mapping; | ||
50 | |||
51 | ret = filemap_write_and_wait(mapping); | ||
52 | if (ret) | ||
53 | return ret; | ||
54 | |||
55 | /*Note: file_fsync below also calles sync_blockdev, which is a no-op | ||
56 | * for exofs, but other then that it does sync_inode and | ||
57 | * sync_superblock which is what we need here. | ||
58 | */ | ||
59 | return file_fsync(filp, dentry, datasync); | ||
60 | } | ||
61 | |||
62 | static int exofs_flush(struct file *file, fl_owner_t id) | ||
63 | { | ||
64 | exofs_file_fsync(file, file->f_path.dentry, 1); | ||
65 | /* TODO: Flush the OSD target */ | ||
66 | return 0; | ||
67 | } | ||
68 | |||
69 | const struct file_operations exofs_file_operations = { | ||
70 | .llseek = generic_file_llseek, | ||
71 | .read = do_sync_read, | ||
72 | .write = do_sync_write, | ||
73 | .aio_read = generic_file_aio_read, | ||
74 | .aio_write = generic_file_aio_write, | ||
75 | .mmap = generic_file_mmap, | ||
76 | .open = generic_file_open, | ||
77 | .release = exofs_release_file, | ||
78 | .fsync = exofs_file_fsync, | ||
79 | .flush = exofs_flush, | ||
80 | .splice_read = generic_file_splice_read, | ||
81 | .splice_write = generic_file_splice_write, | ||
82 | }; | ||
83 | |||
84 | const struct inode_operations exofs_file_inode_operations = { | ||
85 | .truncate = exofs_truncate, | ||
86 | .setattr = exofs_setattr, | ||
87 | }; | ||
diff --git a/fs/exofs/inode.c b/fs/exofs/inode.c new file mode 100644 index 000000000000..ba8d9fab4693 --- /dev/null +++ b/fs/exofs/inode.c | |||
@@ -0,0 +1,1303 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/writeback.h> | ||
37 | #include <linux/buffer_head.h> | ||
38 | #include <scsi/scsi_device.h> | ||
39 | |||
40 | #include "exofs.h" | ||
41 | |||
42 | #ifdef CONFIG_EXOFS_DEBUG | ||
43 | # define EXOFS_DEBUG_OBJ_ISIZE 1 | ||
44 | #endif | ||
45 | |||
46 | struct page_collect { | ||
47 | struct exofs_sb_info *sbi; | ||
48 | struct request_queue *req_q; | ||
49 | struct inode *inode; | ||
50 | unsigned expected_pages; | ||
51 | |||
52 | struct bio *bio; | ||
53 | unsigned nr_pages; | ||
54 | unsigned long length; | ||
55 | loff_t pg_first; /* keep 64bit also in 32-arches */ | ||
56 | }; | ||
57 | |||
58 | static void _pcol_init(struct page_collect *pcol, unsigned expected_pages, | ||
59 | struct inode *inode) | ||
60 | { | ||
61 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | ||
62 | struct request_queue *req_q = sbi->s_dev->scsi_device->request_queue; | ||
63 | |||
64 | pcol->sbi = sbi; | ||
65 | pcol->req_q = req_q; | ||
66 | pcol->inode = inode; | ||
67 | pcol->expected_pages = expected_pages; | ||
68 | |||
69 | pcol->bio = NULL; | ||
70 | pcol->nr_pages = 0; | ||
71 | pcol->length = 0; | ||
72 | pcol->pg_first = -1; | ||
73 | |||
74 | EXOFS_DBGMSG("_pcol_init ino=0x%lx expected_pages=%u\n", inode->i_ino, | ||
75 | expected_pages); | ||
76 | } | ||
77 | |||
78 | static void _pcol_reset(struct page_collect *pcol) | ||
79 | { | ||
80 | pcol->expected_pages -= min(pcol->nr_pages, pcol->expected_pages); | ||
81 | |||
82 | pcol->bio = NULL; | ||
83 | pcol->nr_pages = 0; | ||
84 | pcol->length = 0; | ||
85 | pcol->pg_first = -1; | ||
86 | EXOFS_DBGMSG("_pcol_reset ino=0x%lx expected_pages=%u\n", | ||
87 | pcol->inode->i_ino, pcol->expected_pages); | ||
88 | |||
89 | /* this is probably the end of the loop but in writes | ||
90 | * it might not end here. don't be left with nothing | ||
91 | */ | ||
92 | if (!pcol->expected_pages) | ||
93 | pcol->expected_pages = 128; | ||
94 | } | ||
95 | |||
96 | static int pcol_try_alloc(struct page_collect *pcol) | ||
97 | { | ||
98 | int pages = min_t(unsigned, pcol->expected_pages, BIO_MAX_PAGES); | ||
99 | |||
100 | for (; pages; pages >>= 1) { | ||
101 | pcol->bio = bio_alloc(GFP_KERNEL, pages); | ||
102 | if (likely(pcol->bio)) | ||
103 | return 0; | ||
104 | } | ||
105 | |||
106 | EXOFS_ERR("Failed to kcalloc expected_pages=%u\n", | ||
107 | pcol->expected_pages); | ||
108 | return -ENOMEM; | ||
109 | } | ||
110 | |||
111 | static void pcol_free(struct page_collect *pcol) | ||
112 | { | ||
113 | bio_put(pcol->bio); | ||
114 | pcol->bio = NULL; | ||
115 | } | ||
116 | |||
117 | static int pcol_add_page(struct page_collect *pcol, struct page *page, | ||
118 | unsigned len) | ||
119 | { | ||
120 | int added_len = bio_add_pc_page(pcol->req_q, pcol->bio, page, len, 0); | ||
121 | if (unlikely(len != added_len)) | ||
122 | return -ENOMEM; | ||
123 | |||
124 | ++pcol->nr_pages; | ||
125 | pcol->length += len; | ||
126 | return 0; | ||
127 | } | ||
128 | |||
129 | static int update_read_page(struct page *page, int ret) | ||
130 | { | ||
131 | if (ret == 0) { | ||
132 | /* Everything is OK */ | ||
133 | SetPageUptodate(page); | ||
134 | if (PageError(page)) | ||
135 | ClearPageError(page); | ||
136 | } else if (ret == -EFAULT) { | ||
137 | /* In this case we were trying to read something that wasn't on | ||
138 | * disk yet - return a page full of zeroes. This should be OK, | ||
139 | * because the object should be empty (if there was a write | ||
140 | * before this read, the read would be waiting with the page | ||
141 | * locked */ | ||
142 | clear_highpage(page); | ||
143 | |||
144 | SetPageUptodate(page); | ||
145 | if (PageError(page)) | ||
146 | ClearPageError(page); | ||
147 | ret = 0; /* recovered error */ | ||
148 | EXOFS_DBGMSG("recovered read error\n"); | ||
149 | } else /* Error */ | ||
150 | SetPageError(page); | ||
151 | |||
152 | return ret; | ||
153 | } | ||
154 | |||
155 | static void update_write_page(struct page *page, int ret) | ||
156 | { | ||
157 | if (ret) { | ||
158 | mapping_set_error(page->mapping, ret); | ||
159 | SetPageError(page); | ||
160 | } | ||
161 | end_page_writeback(page); | ||
162 | } | ||
163 | |||
164 | /* Called at the end of reads, to optionally unlock pages and update their | ||
165 | * status. | ||
166 | */ | ||
167 | static int __readpages_done(struct osd_request *or, struct page_collect *pcol, | ||
168 | bool do_unlock) | ||
169 | { | ||
170 | struct bio_vec *bvec; | ||
171 | int i; | ||
172 | u64 resid; | ||
173 | u64 good_bytes; | ||
174 | u64 length = 0; | ||
175 | int ret = exofs_check_ok_resid(or, &resid, NULL); | ||
176 | |||
177 | osd_end_request(or); | ||
178 | |||
179 | if (likely(!ret)) | ||
180 | good_bytes = pcol->length; | ||
181 | else if (!resid) | ||
182 | good_bytes = 0; | ||
183 | else | ||
184 | good_bytes = pcol->length - resid; | ||
185 | |||
186 | EXOFS_DBGMSG("readpages_done(0x%lx) good_bytes=0x%llx" | ||
187 | " length=0x%lx nr_pages=%u\n", | ||
188 | pcol->inode->i_ino, _LLU(good_bytes), pcol->length, | ||
189 | pcol->nr_pages); | ||
190 | |||
191 | __bio_for_each_segment(bvec, pcol->bio, i, 0) { | ||
192 | struct page *page = bvec->bv_page; | ||
193 | struct inode *inode = page->mapping->host; | ||
194 | int page_stat; | ||
195 | |||
196 | if (inode != pcol->inode) | ||
197 | continue; /* osd might add more pages at end */ | ||
198 | |||
199 | if (likely(length < good_bytes)) | ||
200 | page_stat = 0; | ||
201 | else | ||
202 | page_stat = ret; | ||
203 | |||
204 | EXOFS_DBGMSG(" readpages_done(0x%lx, 0x%lx) %s\n", | ||
205 | inode->i_ino, page->index, | ||
206 | page_stat ? "bad_bytes" : "good_bytes"); | ||
207 | |||
208 | ret = update_read_page(page, page_stat); | ||
209 | if (do_unlock) | ||
210 | unlock_page(page); | ||
211 | length += bvec->bv_len; | ||
212 | } | ||
213 | |||
214 | pcol_free(pcol); | ||
215 | EXOFS_DBGMSG("readpages_done END\n"); | ||
216 | return ret; | ||
217 | } | ||
218 | |||
219 | /* callback of async reads */ | ||
220 | static void readpages_done(struct osd_request *or, void *p) | ||
221 | { | ||
222 | struct page_collect *pcol = p; | ||
223 | |||
224 | __readpages_done(or, pcol, true); | ||
225 | atomic_dec(&pcol->sbi->s_curr_pending); | ||
226 | kfree(p); | ||
227 | } | ||
228 | |||
229 | static void _unlock_pcol_pages(struct page_collect *pcol, int ret, int rw) | ||
230 | { | ||
231 | struct bio_vec *bvec; | ||
232 | int i; | ||
233 | |||
234 | __bio_for_each_segment(bvec, pcol->bio, i, 0) { | ||
235 | struct page *page = bvec->bv_page; | ||
236 | |||
237 | if (rw == READ) | ||
238 | update_read_page(page, ret); | ||
239 | else | ||
240 | update_write_page(page, ret); | ||
241 | |||
242 | unlock_page(page); | ||
243 | } | ||
244 | pcol_free(pcol); | ||
245 | } | ||
246 | |||
247 | static int read_exec(struct page_collect *pcol, bool is_sync) | ||
248 | { | ||
249 | struct exofs_i_info *oi = exofs_i(pcol->inode); | ||
250 | struct osd_obj_id obj = {pcol->sbi->s_pid, | ||
251 | pcol->inode->i_ino + EXOFS_OBJ_OFF}; | ||
252 | struct osd_request *or = NULL; | ||
253 | struct page_collect *pcol_copy = NULL; | ||
254 | loff_t i_start = pcol->pg_first << PAGE_CACHE_SHIFT; | ||
255 | int ret; | ||
256 | |||
257 | if (!pcol->bio) | ||
258 | return 0; | ||
259 | |||
260 | /* see comment in _readpage() about sync reads */ | ||
261 | WARN_ON(is_sync && (pcol->nr_pages != 1)); | ||
262 | |||
263 | or = osd_start_request(pcol->sbi->s_dev, GFP_KERNEL); | ||
264 | if (unlikely(!or)) { | ||
265 | ret = -ENOMEM; | ||
266 | goto err; | ||
267 | } | ||
268 | |||
269 | osd_req_read(or, &obj, pcol->bio, i_start); | ||
270 | |||
271 | if (is_sync) { | ||
272 | exofs_sync_op(or, pcol->sbi->s_timeout, oi->i_cred); | ||
273 | return __readpages_done(or, pcol, false); | ||
274 | } | ||
275 | |||
276 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); | ||
277 | if (!pcol_copy) { | ||
278 | ret = -ENOMEM; | ||
279 | goto err; | ||
280 | } | ||
281 | |||
282 | *pcol_copy = *pcol; | ||
283 | ret = exofs_async_op(or, readpages_done, pcol_copy, oi->i_cred); | ||
284 | if (unlikely(ret)) | ||
285 | goto err; | ||
286 | |||
287 | atomic_inc(&pcol->sbi->s_curr_pending); | ||
288 | |||
289 | EXOFS_DBGMSG("read_exec obj=0x%llx start=0x%llx length=0x%lx\n", | ||
290 | obj.id, _LLU(i_start), pcol->length); | ||
291 | |||
292 | /* pages ownership was passed to pcol_copy */ | ||
293 | _pcol_reset(pcol); | ||
294 | return 0; | ||
295 | |||
296 | err: | ||
297 | if (!is_sync) | ||
298 | _unlock_pcol_pages(pcol, ret, READ); | ||
299 | kfree(pcol_copy); | ||
300 | if (or) | ||
301 | osd_end_request(or); | ||
302 | return ret; | ||
303 | } | ||
304 | |||
305 | /* readpage_strip is called either directly from readpage() or by the VFS from | ||
306 | * within read_cache_pages(), to add one more page to be read. It will try to | ||
307 | * collect as many contiguous pages as posible. If a discontinuity is | ||
308 | * encountered, or it runs out of resources, it will submit the previous segment | ||
309 | * and will start a new collection. Eventually caller must submit the last | ||
310 | * segment if present. | ||
311 | */ | ||
312 | static int readpage_strip(void *data, struct page *page) | ||
313 | { | ||
314 | struct page_collect *pcol = data; | ||
315 | struct inode *inode = pcol->inode; | ||
316 | struct exofs_i_info *oi = exofs_i(inode); | ||
317 | loff_t i_size = i_size_read(inode); | ||
318 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; | ||
319 | size_t len; | ||
320 | int ret; | ||
321 | |||
322 | /* FIXME: Just for debugging, will be removed */ | ||
323 | if (PageUptodate(page)) | ||
324 | EXOFS_ERR("PageUptodate(0x%lx, 0x%lx)\n", pcol->inode->i_ino, | ||
325 | page->index); | ||
326 | |||
327 | if (page->index < end_index) | ||
328 | len = PAGE_CACHE_SIZE; | ||
329 | else if (page->index == end_index) | ||
330 | len = i_size & ~PAGE_CACHE_MASK; | ||
331 | else | ||
332 | len = 0; | ||
333 | |||
334 | if (!len || !obj_created(oi)) { | ||
335 | /* this will be out of bounds, or doesn't exist yet. | ||
336 | * Current page is cleared and the request is split | ||
337 | */ | ||
338 | clear_highpage(page); | ||
339 | |||
340 | SetPageUptodate(page); | ||
341 | if (PageError(page)) | ||
342 | ClearPageError(page); | ||
343 | |||
344 | unlock_page(page); | ||
345 | EXOFS_DBGMSG("readpage_strip(0x%lx, 0x%lx) empty page," | ||
346 | " splitting\n", inode->i_ino, page->index); | ||
347 | |||
348 | return read_exec(pcol, false); | ||
349 | } | ||
350 | |||
351 | try_again: | ||
352 | |||
353 | if (unlikely(pcol->pg_first == -1)) { | ||
354 | pcol->pg_first = page->index; | ||
355 | } else if (unlikely((pcol->pg_first + pcol->nr_pages) != | ||
356 | page->index)) { | ||
357 | /* Discontinuity detected, split the request */ | ||
358 | ret = read_exec(pcol, false); | ||
359 | if (unlikely(ret)) | ||
360 | goto fail; | ||
361 | goto try_again; | ||
362 | } | ||
363 | |||
364 | if (!pcol->bio) { | ||
365 | ret = pcol_try_alloc(pcol); | ||
366 | if (unlikely(ret)) | ||
367 | goto fail; | ||
368 | } | ||
369 | |||
370 | if (len != PAGE_CACHE_SIZE) | ||
371 | zero_user(page, len, PAGE_CACHE_SIZE - len); | ||
372 | |||
373 | EXOFS_DBGMSG(" readpage_strip(0x%lx, 0x%lx) len=0x%zx\n", | ||
374 | inode->i_ino, page->index, len); | ||
375 | |||
376 | ret = pcol_add_page(pcol, page, len); | ||
377 | if (ret) { | ||
378 | EXOFS_DBGMSG("Failed pcol_add_page pages[i]=%p " | ||
379 | "this_len=0x%zx nr_pages=%u length=0x%lx\n", | ||
380 | page, len, pcol->nr_pages, pcol->length); | ||
381 | |||
382 | /* split the request, and start again with current page */ | ||
383 | ret = read_exec(pcol, false); | ||
384 | if (unlikely(ret)) | ||
385 | goto fail; | ||
386 | |||
387 | goto try_again; | ||
388 | } | ||
389 | |||
390 | return 0; | ||
391 | |||
392 | fail: | ||
393 | /* SetPageError(page); ??? */ | ||
394 | unlock_page(page); | ||
395 | return ret; | ||
396 | } | ||
397 | |||
398 | static int exofs_readpages(struct file *file, struct address_space *mapping, | ||
399 | struct list_head *pages, unsigned nr_pages) | ||
400 | { | ||
401 | struct page_collect pcol; | ||
402 | int ret; | ||
403 | |||
404 | _pcol_init(&pcol, nr_pages, mapping->host); | ||
405 | |||
406 | ret = read_cache_pages(mapping, pages, readpage_strip, &pcol); | ||
407 | if (ret) { | ||
408 | EXOFS_ERR("read_cache_pages => %d\n", ret); | ||
409 | return ret; | ||
410 | } | ||
411 | |||
412 | return read_exec(&pcol, false); | ||
413 | } | ||
414 | |||
415 | static int _readpage(struct page *page, bool is_sync) | ||
416 | { | ||
417 | struct page_collect pcol; | ||
418 | int ret; | ||
419 | |||
420 | _pcol_init(&pcol, 1, page->mapping->host); | ||
421 | |||
422 | /* readpage_strip might call read_exec(,async) inside at several places | ||
423 | * but this is safe for is_async=0 since read_exec will not do anything | ||
424 | * when we have a single page. | ||
425 | */ | ||
426 | ret = readpage_strip(&pcol, page); | ||
427 | if (ret) { | ||
428 | EXOFS_ERR("_readpage => %d\n", ret); | ||
429 | return ret; | ||
430 | } | ||
431 | |||
432 | return read_exec(&pcol, is_sync); | ||
433 | } | ||
434 | |||
435 | /* | ||
436 | * We don't need the file | ||
437 | */ | ||
438 | static int exofs_readpage(struct file *file, struct page *page) | ||
439 | { | ||
440 | return _readpage(page, false); | ||
441 | } | ||
442 | |||
443 | /* Callback for osd_write. All writes are asynchronouse */ | ||
444 | static void writepages_done(struct osd_request *or, void *p) | ||
445 | { | ||
446 | struct page_collect *pcol = p; | ||
447 | struct bio_vec *bvec; | ||
448 | int i; | ||
449 | u64 resid; | ||
450 | u64 good_bytes; | ||
451 | u64 length = 0; | ||
452 | |||
453 | int ret = exofs_check_ok_resid(or, NULL, &resid); | ||
454 | |||
455 | osd_end_request(or); | ||
456 | atomic_dec(&pcol->sbi->s_curr_pending); | ||
457 | |||
458 | if (likely(!ret)) | ||
459 | good_bytes = pcol->length; | ||
460 | else if (!resid) | ||
461 | good_bytes = 0; | ||
462 | else | ||
463 | good_bytes = pcol->length - resid; | ||
464 | |||
465 | EXOFS_DBGMSG("writepages_done(0x%lx) good_bytes=0x%llx" | ||
466 | " length=0x%lx nr_pages=%u\n", | ||
467 | pcol->inode->i_ino, _LLU(good_bytes), pcol->length, | ||
468 | pcol->nr_pages); | ||
469 | |||
470 | __bio_for_each_segment(bvec, pcol->bio, i, 0) { | ||
471 | struct page *page = bvec->bv_page; | ||
472 | struct inode *inode = page->mapping->host; | ||
473 | int page_stat; | ||
474 | |||
475 | if (inode != pcol->inode) | ||
476 | continue; /* osd might add more pages to a bio */ | ||
477 | |||
478 | if (likely(length < good_bytes)) | ||
479 | page_stat = 0; | ||
480 | else | ||
481 | page_stat = ret; | ||
482 | |||
483 | update_write_page(page, page_stat); | ||
484 | unlock_page(page); | ||
485 | EXOFS_DBGMSG(" writepages_done(0x%lx, 0x%lx) status=%d\n", | ||
486 | inode->i_ino, page->index, page_stat); | ||
487 | |||
488 | length += bvec->bv_len; | ||
489 | } | ||
490 | |||
491 | pcol_free(pcol); | ||
492 | kfree(pcol); | ||
493 | EXOFS_DBGMSG("writepages_done END\n"); | ||
494 | } | ||
495 | |||
496 | static int write_exec(struct page_collect *pcol) | ||
497 | { | ||
498 | struct exofs_i_info *oi = exofs_i(pcol->inode); | ||
499 | struct osd_obj_id obj = {pcol->sbi->s_pid, | ||
500 | pcol->inode->i_ino + EXOFS_OBJ_OFF}; | ||
501 | struct osd_request *or = NULL; | ||
502 | struct page_collect *pcol_copy = NULL; | ||
503 | loff_t i_start = pcol->pg_first << PAGE_CACHE_SHIFT; | ||
504 | int ret; | ||
505 | |||
506 | if (!pcol->bio) | ||
507 | return 0; | ||
508 | |||
509 | or = osd_start_request(pcol->sbi->s_dev, GFP_KERNEL); | ||
510 | if (unlikely(!or)) { | ||
511 | EXOFS_ERR("write_exec: Faild to osd_start_request()\n"); | ||
512 | ret = -ENOMEM; | ||
513 | goto err; | ||
514 | } | ||
515 | |||
516 | pcol_copy = kmalloc(sizeof(*pcol_copy), GFP_KERNEL); | ||
517 | if (!pcol_copy) { | ||
518 | EXOFS_ERR("write_exec: Faild to kmalloc(pcol)\n"); | ||
519 | ret = -ENOMEM; | ||
520 | goto err; | ||
521 | } | ||
522 | |||
523 | *pcol_copy = *pcol; | ||
524 | |||
525 | osd_req_write(or, &obj, pcol_copy->bio, i_start); | ||
526 | ret = exofs_async_op(or, writepages_done, pcol_copy, oi->i_cred); | ||
527 | if (unlikely(ret)) { | ||
528 | EXOFS_ERR("write_exec: exofs_async_op() Faild\n"); | ||
529 | goto err; | ||
530 | } | ||
531 | |||
532 | atomic_inc(&pcol->sbi->s_curr_pending); | ||
533 | EXOFS_DBGMSG("write_exec(0x%lx, 0x%llx) start=0x%llx length=0x%lx\n", | ||
534 | pcol->inode->i_ino, pcol->pg_first, _LLU(i_start), | ||
535 | pcol->length); | ||
536 | /* pages ownership was passed to pcol_copy */ | ||
537 | _pcol_reset(pcol); | ||
538 | return 0; | ||
539 | |||
540 | err: | ||
541 | _unlock_pcol_pages(pcol, ret, WRITE); | ||
542 | kfree(pcol_copy); | ||
543 | if (or) | ||
544 | osd_end_request(or); | ||
545 | return ret; | ||
546 | } | ||
547 | |||
548 | /* writepage_strip is called either directly from writepage() or by the VFS from | ||
549 | * within write_cache_pages(), to add one more page to be written to storage. | ||
550 | * It will try to collect as many contiguous pages as possible. If a | ||
551 | * discontinuity is encountered or it runs out of resources it will submit the | ||
552 | * previous segment and will start a new collection. | ||
553 | * Eventually caller must submit the last segment if present. | ||
554 | */ | ||
555 | static int writepage_strip(struct page *page, | ||
556 | struct writeback_control *wbc_unused, void *data) | ||
557 | { | ||
558 | struct page_collect *pcol = data; | ||
559 | struct inode *inode = pcol->inode; | ||
560 | struct exofs_i_info *oi = exofs_i(inode); | ||
561 | loff_t i_size = i_size_read(inode); | ||
562 | pgoff_t end_index = i_size >> PAGE_CACHE_SHIFT; | ||
563 | size_t len; | ||
564 | int ret; | ||
565 | |||
566 | BUG_ON(!PageLocked(page)); | ||
567 | |||
568 | ret = wait_obj_created(oi); | ||
569 | if (unlikely(ret)) | ||
570 | goto fail; | ||
571 | |||
572 | if (page->index < end_index) | ||
573 | /* in this case, the page is within the limits of the file */ | ||
574 | len = PAGE_CACHE_SIZE; | ||
575 | else { | ||
576 | len = i_size & ~PAGE_CACHE_MASK; | ||
577 | |||
578 | if (page->index > end_index || !len) { | ||
579 | /* in this case, the page is outside the limits | ||
580 | * (truncate in progress) | ||
581 | */ | ||
582 | ret = write_exec(pcol); | ||
583 | if (unlikely(ret)) | ||
584 | goto fail; | ||
585 | if (PageError(page)) | ||
586 | ClearPageError(page); | ||
587 | unlock_page(page); | ||
588 | return 0; | ||
589 | } | ||
590 | } | ||
591 | |||
592 | try_again: | ||
593 | |||
594 | if (unlikely(pcol->pg_first == -1)) { | ||
595 | pcol->pg_first = page->index; | ||
596 | } else if (unlikely((pcol->pg_first + pcol->nr_pages) != | ||
597 | page->index)) { | ||
598 | /* Discontinuity detected, split the request */ | ||
599 | ret = write_exec(pcol); | ||
600 | if (unlikely(ret)) | ||
601 | goto fail; | ||
602 | goto try_again; | ||
603 | } | ||
604 | |||
605 | if (!pcol->bio) { | ||
606 | ret = pcol_try_alloc(pcol); | ||
607 | if (unlikely(ret)) | ||
608 | goto fail; | ||
609 | } | ||
610 | |||
611 | EXOFS_DBGMSG(" writepage_strip(0x%lx, 0x%lx) len=0x%zx\n", | ||
612 | inode->i_ino, page->index, len); | ||
613 | |||
614 | ret = pcol_add_page(pcol, page, len); | ||
615 | if (unlikely(ret)) { | ||
616 | EXOFS_DBGMSG("Failed pcol_add_page " | ||
617 | "nr_pages=%u total_length=0x%lx\n", | ||
618 | pcol->nr_pages, pcol->length); | ||
619 | |||
620 | /* split the request, next loop will start again */ | ||
621 | ret = write_exec(pcol); | ||
622 | if (unlikely(ret)) { | ||
623 | EXOFS_DBGMSG("write_exec faild => %d", ret); | ||
624 | goto fail; | ||
625 | } | ||
626 | |||
627 | goto try_again; | ||
628 | } | ||
629 | |||
630 | BUG_ON(PageWriteback(page)); | ||
631 | set_page_writeback(page); | ||
632 | |||
633 | return 0; | ||
634 | |||
635 | fail: | ||
636 | set_bit(AS_EIO, &page->mapping->flags); | ||
637 | unlock_page(page); | ||
638 | return ret; | ||
639 | } | ||
640 | |||
641 | static int exofs_writepages(struct address_space *mapping, | ||
642 | struct writeback_control *wbc) | ||
643 | { | ||
644 | struct page_collect pcol; | ||
645 | long start, end, expected_pages; | ||
646 | int ret; | ||
647 | |||
648 | start = wbc->range_start >> PAGE_CACHE_SHIFT; | ||
649 | end = (wbc->range_end == LLONG_MAX) ? | ||
650 | start + mapping->nrpages : | ||
651 | wbc->range_end >> PAGE_CACHE_SHIFT; | ||
652 | |||
653 | if (start || end) | ||
654 | expected_pages = min(end - start + 1, 32L); | ||
655 | else | ||
656 | expected_pages = mapping->nrpages; | ||
657 | |||
658 | EXOFS_DBGMSG("inode(0x%lx) wbc->start=0x%llx wbc->end=0x%llx" | ||
659 | " m->nrpages=%lu start=0x%lx end=0x%lx\n", | ||
660 | mapping->host->i_ino, wbc->range_start, wbc->range_end, | ||
661 | mapping->nrpages, start, end); | ||
662 | |||
663 | _pcol_init(&pcol, expected_pages, mapping->host); | ||
664 | |||
665 | ret = write_cache_pages(mapping, wbc, writepage_strip, &pcol); | ||
666 | if (ret) { | ||
667 | EXOFS_ERR("write_cache_pages => %d\n", ret); | ||
668 | return ret; | ||
669 | } | ||
670 | |||
671 | return write_exec(&pcol); | ||
672 | } | ||
673 | |||
674 | static int exofs_writepage(struct page *page, struct writeback_control *wbc) | ||
675 | { | ||
676 | struct page_collect pcol; | ||
677 | int ret; | ||
678 | |||
679 | _pcol_init(&pcol, 1, page->mapping->host); | ||
680 | |||
681 | ret = writepage_strip(page, NULL, &pcol); | ||
682 | if (ret) { | ||
683 | EXOFS_ERR("exofs_writepage => %d\n", ret); | ||
684 | return ret; | ||
685 | } | ||
686 | |||
687 | return write_exec(&pcol); | ||
688 | } | ||
689 | |||
690 | int exofs_write_begin(struct file *file, struct address_space *mapping, | ||
691 | loff_t pos, unsigned len, unsigned flags, | ||
692 | struct page **pagep, void **fsdata) | ||
693 | { | ||
694 | int ret = 0; | ||
695 | struct page *page; | ||
696 | |||
697 | page = *pagep; | ||
698 | if (page == NULL) { | ||
699 | ret = simple_write_begin(file, mapping, pos, len, flags, pagep, | ||
700 | fsdata); | ||
701 | if (ret) { | ||
702 | EXOFS_DBGMSG("simple_write_begin faild\n"); | ||
703 | return ret; | ||
704 | } | ||
705 | |||
706 | page = *pagep; | ||
707 | } | ||
708 | |||
709 | /* read modify write */ | ||
710 | if (!PageUptodate(page) && (len != PAGE_CACHE_SIZE)) { | ||
711 | ret = _readpage(page, true); | ||
712 | if (ret) { | ||
713 | /*SetPageError was done by _readpage. Is it ok?*/ | ||
714 | unlock_page(page); | ||
715 | EXOFS_DBGMSG("__readpage_filler faild\n"); | ||
716 | } | ||
717 | } | ||
718 | |||
719 | return ret; | ||
720 | } | ||
721 | |||
722 | static int exofs_write_begin_export(struct file *file, | ||
723 | struct address_space *mapping, | ||
724 | loff_t pos, unsigned len, unsigned flags, | ||
725 | struct page **pagep, void **fsdata) | ||
726 | { | ||
727 | *pagep = NULL; | ||
728 | |||
729 | return exofs_write_begin(file, mapping, pos, len, flags, pagep, | ||
730 | fsdata); | ||
731 | } | ||
732 | |||
733 | const struct address_space_operations exofs_aops = { | ||
734 | .readpage = exofs_readpage, | ||
735 | .readpages = exofs_readpages, | ||
736 | .writepage = exofs_writepage, | ||
737 | .writepages = exofs_writepages, | ||
738 | .write_begin = exofs_write_begin_export, | ||
739 | .write_end = simple_write_end, | ||
740 | }; | ||
741 | |||
742 | /****************************************************************************** | ||
743 | * INODE OPERATIONS | ||
744 | *****************************************************************************/ | ||
745 | |||
746 | /* | ||
747 | * Test whether an inode is a fast symlink. | ||
748 | */ | ||
749 | static inline int exofs_inode_is_fast_symlink(struct inode *inode) | ||
750 | { | ||
751 | struct exofs_i_info *oi = exofs_i(inode); | ||
752 | |||
753 | return S_ISLNK(inode->i_mode) && (oi->i_data[0] != 0); | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * get_block_t - Fill in a buffer_head | ||
758 | * An OSD takes care of block allocation so we just fake an allocation by | ||
759 | * putting in the inode's sector_t in the buffer_head. | ||
760 | * TODO: What about the case of create==0 and @iblock does not exist in the | ||
761 | * object? | ||
762 | */ | ||
763 | static int exofs_get_block(struct inode *inode, sector_t iblock, | ||
764 | struct buffer_head *bh_result, int create) | ||
765 | { | ||
766 | map_bh(bh_result, inode->i_sb, iblock); | ||
767 | return 0; | ||
768 | } | ||
769 | |||
770 | const struct osd_attr g_attr_logical_length = ATTR_DEF( | ||
771 | OSD_APAGE_OBJECT_INFORMATION, OSD_ATTR_OI_LOGICAL_LENGTH, 8); | ||
772 | |||
773 | /* | ||
774 | * Truncate a file to the specified size - all we have to do is set the size | ||
775 | * attribute. We make sure the object exists first. | ||
776 | */ | ||
777 | void exofs_truncate(struct inode *inode) | ||
778 | { | ||
779 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | ||
780 | struct exofs_i_info *oi = exofs_i(inode); | ||
781 | struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; | ||
782 | struct osd_request *or; | ||
783 | struct osd_attr attr; | ||
784 | loff_t isize = i_size_read(inode); | ||
785 | __be64 newsize; | ||
786 | int ret; | ||
787 | |||
788 | if (!(S_ISREG(inode->i_mode) || S_ISDIR(inode->i_mode) | ||
789 | || S_ISLNK(inode->i_mode))) | ||
790 | return; | ||
791 | if (exofs_inode_is_fast_symlink(inode)) | ||
792 | return; | ||
793 | if (IS_APPEND(inode) || IS_IMMUTABLE(inode)) | ||
794 | return; | ||
795 | inode->i_mtime = inode->i_ctime = CURRENT_TIME; | ||
796 | |||
797 | nobh_truncate_page(inode->i_mapping, isize, exofs_get_block); | ||
798 | |||
799 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
800 | if (unlikely(!or)) { | ||
801 | EXOFS_ERR("ERROR: exofs_truncate: osd_start_request failed\n"); | ||
802 | goto fail; | ||
803 | } | ||
804 | |||
805 | osd_req_set_attributes(or, &obj); | ||
806 | |||
807 | newsize = cpu_to_be64((u64)isize); | ||
808 | attr = g_attr_logical_length; | ||
809 | attr.val_ptr = &newsize; | ||
810 | osd_req_add_set_attr_list(or, &attr, 1); | ||
811 | |||
812 | /* if we are about to truncate an object, and it hasn't been | ||
813 | * created yet, wait | ||
814 | */ | ||
815 | if (unlikely(wait_obj_created(oi))) | ||
816 | goto fail; | ||
817 | |||
818 | ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); | ||
819 | osd_end_request(or); | ||
820 | if (ret) | ||
821 | goto fail; | ||
822 | |||
823 | out: | ||
824 | mark_inode_dirty(inode); | ||
825 | return; | ||
826 | fail: | ||
827 | make_bad_inode(inode); | ||
828 | goto out; | ||
829 | } | ||
830 | |||
831 | /* | ||
832 | * Set inode attributes - just call generic functions. | ||
833 | */ | ||
834 | int exofs_setattr(struct dentry *dentry, struct iattr *iattr) | ||
835 | { | ||
836 | struct inode *inode = dentry->d_inode; | ||
837 | int error; | ||
838 | |||
839 | error = inode_change_ok(inode, iattr); | ||
840 | if (error) | ||
841 | return error; | ||
842 | |||
843 | error = inode_setattr(inode, iattr); | ||
844 | return error; | ||
845 | } | ||
846 | |||
847 | /* | ||
848 | * Read an inode from the OSD, and return it as is. We also return the size | ||
849 | * attribute in the 'sanity' argument if we got compiled with debugging turned | ||
850 | * on. | ||
851 | */ | ||
852 | static int exofs_get_inode(struct super_block *sb, struct exofs_i_info *oi, | ||
853 | struct exofs_fcb *inode, uint64_t *sanity) | ||
854 | { | ||
855 | struct exofs_sb_info *sbi = sb->s_fs_info; | ||
856 | struct osd_request *or; | ||
857 | struct osd_attr attr; | ||
858 | struct osd_obj_id obj = {sbi->s_pid, | ||
859 | oi->vfs_inode.i_ino + EXOFS_OBJ_OFF}; | ||
860 | int ret; | ||
861 | |||
862 | exofs_make_credential(oi->i_cred, &obj); | ||
863 | |||
864 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
865 | if (unlikely(!or)) { | ||
866 | EXOFS_ERR("exofs_get_inode: osd_start_request failed.\n"); | ||
867 | return -ENOMEM; | ||
868 | } | ||
869 | osd_req_get_attributes(or, &obj); | ||
870 | |||
871 | /* we need the inode attribute */ | ||
872 | osd_req_add_get_attr_list(or, &g_attr_inode_data, 1); | ||
873 | |||
874 | #ifdef EXOFS_DEBUG_OBJ_ISIZE | ||
875 | /* we get the size attributes to do a sanity check */ | ||
876 | osd_req_add_get_attr_list(or, &g_attr_logical_length, 1); | ||
877 | #endif | ||
878 | |||
879 | ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); | ||
880 | if (ret) | ||
881 | goto out; | ||
882 | |||
883 | attr = g_attr_inode_data; | ||
884 | ret = extract_attr_from_req(or, &attr); | ||
885 | if (ret) { | ||
886 | EXOFS_ERR("exofs_get_inode: extract_attr_from_req failed\n"); | ||
887 | goto out; | ||
888 | } | ||
889 | |||
890 | WARN_ON(attr.len != EXOFS_INO_ATTR_SIZE); | ||
891 | memcpy(inode, attr.val_ptr, EXOFS_INO_ATTR_SIZE); | ||
892 | |||
893 | #ifdef EXOFS_DEBUG_OBJ_ISIZE | ||
894 | attr = g_attr_logical_length; | ||
895 | ret = extract_attr_from_req(or, &attr); | ||
896 | if (ret) { | ||
897 | EXOFS_ERR("ERROR: extract attr from or failed\n"); | ||
898 | goto out; | ||
899 | } | ||
900 | *sanity = get_unaligned_be64(attr.val_ptr); | ||
901 | #endif | ||
902 | |||
903 | out: | ||
904 | osd_end_request(or); | ||
905 | return ret; | ||
906 | } | ||
907 | |||
908 | /* | ||
909 | * Fill in an inode read from the OSD and set it up for use | ||
910 | */ | ||
911 | struct inode *exofs_iget(struct super_block *sb, unsigned long ino) | ||
912 | { | ||
913 | struct exofs_i_info *oi; | ||
914 | struct exofs_fcb fcb; | ||
915 | struct inode *inode; | ||
916 | uint64_t uninitialized_var(sanity); | ||
917 | int ret; | ||
918 | |||
919 | inode = iget_locked(sb, ino); | ||
920 | if (!inode) | ||
921 | return ERR_PTR(-ENOMEM); | ||
922 | if (!(inode->i_state & I_NEW)) | ||
923 | return inode; | ||
924 | oi = exofs_i(inode); | ||
925 | |||
926 | /* read the inode from the osd */ | ||
927 | ret = exofs_get_inode(sb, oi, &fcb, &sanity); | ||
928 | if (ret) | ||
929 | goto bad_inode; | ||
930 | |||
931 | init_waitqueue_head(&oi->i_wq); | ||
932 | set_obj_created(oi); | ||
933 | |||
934 | /* copy stuff from on-disk struct to in-memory struct */ | ||
935 | inode->i_mode = le16_to_cpu(fcb.i_mode); | ||
936 | inode->i_uid = le32_to_cpu(fcb.i_uid); | ||
937 | inode->i_gid = le32_to_cpu(fcb.i_gid); | ||
938 | inode->i_nlink = le16_to_cpu(fcb.i_links_count); | ||
939 | inode->i_ctime.tv_sec = (signed)le32_to_cpu(fcb.i_ctime); | ||
940 | inode->i_atime.tv_sec = (signed)le32_to_cpu(fcb.i_atime); | ||
941 | inode->i_mtime.tv_sec = (signed)le32_to_cpu(fcb.i_mtime); | ||
942 | inode->i_ctime.tv_nsec = | ||
943 | inode->i_atime.tv_nsec = inode->i_mtime.tv_nsec = 0; | ||
944 | oi->i_commit_size = le64_to_cpu(fcb.i_size); | ||
945 | i_size_write(inode, oi->i_commit_size); | ||
946 | inode->i_blkbits = EXOFS_BLKSHIFT; | ||
947 | inode->i_generation = le32_to_cpu(fcb.i_generation); | ||
948 | |||
949 | #ifdef EXOFS_DEBUG_OBJ_ISIZE | ||
950 | if ((inode->i_size != sanity) && | ||
951 | (!exofs_inode_is_fast_symlink(inode))) { | ||
952 | EXOFS_ERR("WARNING: Size of object from inode and " | ||
953 | "attributes differ (%lld != %llu)\n", | ||
954 | inode->i_size, _LLU(sanity)); | ||
955 | } | ||
956 | #endif | ||
957 | |||
958 | oi->i_dir_start_lookup = 0; | ||
959 | |||
960 | if ((inode->i_nlink == 0) && (inode->i_mode == 0)) { | ||
961 | ret = -ESTALE; | ||
962 | goto bad_inode; | ||
963 | } | ||
964 | |||
965 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | ||
966 | if (fcb.i_data[0]) | ||
967 | inode->i_rdev = | ||
968 | old_decode_dev(le32_to_cpu(fcb.i_data[0])); | ||
969 | else | ||
970 | inode->i_rdev = | ||
971 | new_decode_dev(le32_to_cpu(fcb.i_data[1])); | ||
972 | } else { | ||
973 | memcpy(oi->i_data, fcb.i_data, sizeof(fcb.i_data)); | ||
974 | } | ||
975 | |||
976 | if (S_ISREG(inode->i_mode)) { | ||
977 | inode->i_op = &exofs_file_inode_operations; | ||
978 | inode->i_fop = &exofs_file_operations; | ||
979 | inode->i_mapping->a_ops = &exofs_aops; | ||
980 | } else if (S_ISDIR(inode->i_mode)) { | ||
981 | inode->i_op = &exofs_dir_inode_operations; | ||
982 | inode->i_fop = &exofs_dir_operations; | ||
983 | inode->i_mapping->a_ops = &exofs_aops; | ||
984 | } else if (S_ISLNK(inode->i_mode)) { | ||
985 | if (exofs_inode_is_fast_symlink(inode)) | ||
986 | inode->i_op = &exofs_fast_symlink_inode_operations; | ||
987 | else { | ||
988 | inode->i_op = &exofs_symlink_inode_operations; | ||
989 | inode->i_mapping->a_ops = &exofs_aops; | ||
990 | } | ||
991 | } else { | ||
992 | inode->i_op = &exofs_special_inode_operations; | ||
993 | if (fcb.i_data[0]) | ||
994 | init_special_inode(inode, inode->i_mode, | ||
995 | old_decode_dev(le32_to_cpu(fcb.i_data[0]))); | ||
996 | else | ||
997 | init_special_inode(inode, inode->i_mode, | ||
998 | new_decode_dev(le32_to_cpu(fcb.i_data[1]))); | ||
999 | } | ||
1000 | |||
1001 | unlock_new_inode(inode); | ||
1002 | return inode; | ||
1003 | |||
1004 | bad_inode: | ||
1005 | iget_failed(inode); | ||
1006 | return ERR_PTR(ret); | ||
1007 | } | ||
1008 | |||
1009 | int __exofs_wait_obj_created(struct exofs_i_info *oi) | ||
1010 | { | ||
1011 | if (!obj_created(oi)) { | ||
1012 | BUG_ON(!obj_2bcreated(oi)); | ||
1013 | wait_event(oi->i_wq, obj_created(oi)); | ||
1014 | } | ||
1015 | return unlikely(is_bad_inode(&oi->vfs_inode)) ? -EIO : 0; | ||
1016 | } | ||
1017 | /* | ||
1018 | * Callback function from exofs_new_inode(). The important thing is that we | ||
1019 | * set the obj_created flag so that other methods know that the object exists on | ||
1020 | * the OSD. | ||
1021 | */ | ||
1022 | static void create_done(struct osd_request *or, void *p) | ||
1023 | { | ||
1024 | struct inode *inode = p; | ||
1025 | struct exofs_i_info *oi = exofs_i(inode); | ||
1026 | struct exofs_sb_info *sbi = inode->i_sb->s_fs_info; | ||
1027 | int ret; | ||
1028 | |||
1029 | ret = exofs_check_ok(or); | ||
1030 | osd_end_request(or); | ||
1031 | atomic_dec(&sbi->s_curr_pending); | ||
1032 | |||
1033 | if (unlikely(ret)) { | ||
1034 | EXOFS_ERR("object=0x%llx creation faild in pid=0x%llx", | ||
1035 | _LLU(sbi->s_pid), _LLU(inode->i_ino + EXOFS_OBJ_OFF)); | ||
1036 | make_bad_inode(inode); | ||
1037 | } else | ||
1038 | set_obj_created(oi); | ||
1039 | |||
1040 | atomic_dec(&inode->i_count); | ||
1041 | wake_up(&oi->i_wq); | ||
1042 | } | ||
1043 | |||
1044 | /* | ||
1045 | * Set up a new inode and create an object for it on the OSD | ||
1046 | */ | ||
1047 | struct inode *exofs_new_inode(struct inode *dir, int mode) | ||
1048 | { | ||
1049 | struct super_block *sb; | ||
1050 | struct inode *inode; | ||
1051 | struct exofs_i_info *oi; | ||
1052 | struct exofs_sb_info *sbi; | ||
1053 | struct osd_request *or; | ||
1054 | struct osd_obj_id obj; | ||
1055 | int ret; | ||
1056 | |||
1057 | sb = dir->i_sb; | ||
1058 | inode = new_inode(sb); | ||
1059 | if (!inode) | ||
1060 | return ERR_PTR(-ENOMEM); | ||
1061 | |||
1062 | oi = exofs_i(inode); | ||
1063 | |||
1064 | init_waitqueue_head(&oi->i_wq); | ||
1065 | set_obj_2bcreated(oi); | ||
1066 | |||
1067 | sbi = sb->s_fs_info; | ||
1068 | |||
1069 | sb->s_dirt = 1; | ||
1070 | inode->i_uid = current->cred->fsuid; | ||
1071 | if (dir->i_mode & S_ISGID) { | ||
1072 | inode->i_gid = dir->i_gid; | ||
1073 | if (S_ISDIR(mode)) | ||
1074 | mode |= S_ISGID; | ||
1075 | } else { | ||
1076 | inode->i_gid = current->cred->fsgid; | ||
1077 | } | ||
1078 | inode->i_mode = mode; | ||
1079 | |||
1080 | inode->i_ino = sbi->s_nextid++; | ||
1081 | inode->i_blkbits = EXOFS_BLKSHIFT; | ||
1082 | inode->i_mtime = inode->i_atime = inode->i_ctime = CURRENT_TIME; | ||
1083 | oi->i_commit_size = inode->i_size = 0; | ||
1084 | spin_lock(&sbi->s_next_gen_lock); | ||
1085 | inode->i_generation = sbi->s_next_generation++; | ||
1086 | spin_unlock(&sbi->s_next_gen_lock); | ||
1087 | insert_inode_hash(inode); | ||
1088 | |||
1089 | mark_inode_dirty(inode); | ||
1090 | |||
1091 | obj.partition = sbi->s_pid; | ||
1092 | obj.id = inode->i_ino + EXOFS_OBJ_OFF; | ||
1093 | exofs_make_credential(oi->i_cred, &obj); | ||
1094 | |||
1095 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
1096 | if (unlikely(!or)) { | ||
1097 | EXOFS_ERR("exofs_new_inode: osd_start_request failed\n"); | ||
1098 | return ERR_PTR(-ENOMEM); | ||
1099 | } | ||
1100 | |||
1101 | osd_req_create_object(or, &obj); | ||
1102 | |||
1103 | /* increment the refcount so that the inode will still be around when we | ||
1104 | * reach the callback | ||
1105 | */ | ||
1106 | atomic_inc(&inode->i_count); | ||
1107 | |||
1108 | ret = exofs_async_op(or, create_done, inode, oi->i_cred); | ||
1109 | if (ret) { | ||
1110 | atomic_dec(&inode->i_count); | ||
1111 | osd_end_request(or); | ||
1112 | return ERR_PTR(-EIO); | ||
1113 | } | ||
1114 | atomic_inc(&sbi->s_curr_pending); | ||
1115 | |||
1116 | return inode; | ||
1117 | } | ||
1118 | |||
1119 | /* | ||
1120 | * struct to pass two arguments to update_inode's callback | ||
1121 | */ | ||
1122 | struct updatei_args { | ||
1123 | struct exofs_sb_info *sbi; | ||
1124 | struct exofs_fcb fcb; | ||
1125 | }; | ||
1126 | |||
1127 | /* | ||
1128 | * Callback function from exofs_update_inode(). | ||
1129 | */ | ||
1130 | static void updatei_done(struct osd_request *or, void *p) | ||
1131 | { | ||
1132 | struct updatei_args *args = p; | ||
1133 | |||
1134 | osd_end_request(or); | ||
1135 | |||
1136 | atomic_dec(&args->sbi->s_curr_pending); | ||
1137 | |||
1138 | kfree(args); | ||
1139 | } | ||
1140 | |||
1141 | /* | ||
1142 | * Write the inode to the OSD. Just fill up the struct, and set the attribute | ||
1143 | * synchronously or asynchronously depending on the do_sync flag. | ||
1144 | */ | ||
1145 | static int exofs_update_inode(struct inode *inode, int do_sync) | ||
1146 | { | ||
1147 | struct exofs_i_info *oi = exofs_i(inode); | ||
1148 | struct super_block *sb = inode->i_sb; | ||
1149 | struct exofs_sb_info *sbi = sb->s_fs_info; | ||
1150 | struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; | ||
1151 | struct osd_request *or; | ||
1152 | struct osd_attr attr; | ||
1153 | struct exofs_fcb *fcb; | ||
1154 | struct updatei_args *args; | ||
1155 | int ret; | ||
1156 | |||
1157 | args = kzalloc(sizeof(*args), GFP_KERNEL); | ||
1158 | if (!args) | ||
1159 | return -ENOMEM; | ||
1160 | |||
1161 | fcb = &args->fcb; | ||
1162 | |||
1163 | fcb->i_mode = cpu_to_le16(inode->i_mode); | ||
1164 | fcb->i_uid = cpu_to_le32(inode->i_uid); | ||
1165 | fcb->i_gid = cpu_to_le32(inode->i_gid); | ||
1166 | fcb->i_links_count = cpu_to_le16(inode->i_nlink); | ||
1167 | fcb->i_ctime = cpu_to_le32(inode->i_ctime.tv_sec); | ||
1168 | fcb->i_atime = cpu_to_le32(inode->i_atime.tv_sec); | ||
1169 | fcb->i_mtime = cpu_to_le32(inode->i_mtime.tv_sec); | ||
1170 | oi->i_commit_size = i_size_read(inode); | ||
1171 | fcb->i_size = cpu_to_le64(oi->i_commit_size); | ||
1172 | fcb->i_generation = cpu_to_le32(inode->i_generation); | ||
1173 | |||
1174 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | ||
1175 | if (old_valid_dev(inode->i_rdev)) { | ||
1176 | fcb->i_data[0] = | ||
1177 | cpu_to_le32(old_encode_dev(inode->i_rdev)); | ||
1178 | fcb->i_data[1] = 0; | ||
1179 | } else { | ||
1180 | fcb->i_data[0] = 0; | ||
1181 | fcb->i_data[1] = | ||
1182 | cpu_to_le32(new_encode_dev(inode->i_rdev)); | ||
1183 | fcb->i_data[2] = 0; | ||
1184 | } | ||
1185 | } else | ||
1186 | memcpy(fcb->i_data, oi->i_data, sizeof(fcb->i_data)); | ||
1187 | |||
1188 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
1189 | if (unlikely(!or)) { | ||
1190 | EXOFS_ERR("exofs_update_inode: osd_start_request failed.\n"); | ||
1191 | ret = -ENOMEM; | ||
1192 | goto free_args; | ||
1193 | } | ||
1194 | |||
1195 | osd_req_set_attributes(or, &obj); | ||
1196 | |||
1197 | attr = g_attr_inode_data; | ||
1198 | attr.val_ptr = fcb; | ||
1199 | osd_req_add_set_attr_list(or, &attr, 1); | ||
1200 | |||
1201 | if (!obj_created(oi)) { | ||
1202 | EXOFS_DBGMSG("!obj_created\n"); | ||
1203 | BUG_ON(!obj_2bcreated(oi)); | ||
1204 | wait_event(oi->i_wq, obj_created(oi)); | ||
1205 | EXOFS_DBGMSG("wait_event done\n"); | ||
1206 | } | ||
1207 | |||
1208 | if (do_sync) { | ||
1209 | ret = exofs_sync_op(or, sbi->s_timeout, oi->i_cred); | ||
1210 | osd_end_request(or); | ||
1211 | goto free_args; | ||
1212 | } else { | ||
1213 | args->sbi = sbi; | ||
1214 | |||
1215 | ret = exofs_async_op(or, updatei_done, args, oi->i_cred); | ||
1216 | if (ret) { | ||
1217 | osd_end_request(or); | ||
1218 | goto free_args; | ||
1219 | } | ||
1220 | atomic_inc(&sbi->s_curr_pending); | ||
1221 | goto out; /* deallocation in updatei_done */ | ||
1222 | } | ||
1223 | |||
1224 | free_args: | ||
1225 | kfree(args); | ||
1226 | out: | ||
1227 | EXOFS_DBGMSG("ret=>%d\n", ret); | ||
1228 | return ret; | ||
1229 | } | ||
1230 | |||
1231 | int exofs_write_inode(struct inode *inode, int wait) | ||
1232 | { | ||
1233 | return exofs_update_inode(inode, wait); | ||
1234 | } | ||
1235 | |||
1236 | /* | ||
1237 | * Callback function from exofs_delete_inode() - don't have much cleaning up to | ||
1238 | * do. | ||
1239 | */ | ||
1240 | static void delete_done(struct osd_request *or, void *p) | ||
1241 | { | ||
1242 | struct exofs_sb_info *sbi; | ||
1243 | osd_end_request(or); | ||
1244 | sbi = p; | ||
1245 | atomic_dec(&sbi->s_curr_pending); | ||
1246 | } | ||
1247 | |||
1248 | /* | ||
1249 | * Called when the refcount of an inode reaches zero. We remove the object | ||
1250 | * from the OSD here. We make sure the object was created before we try and | ||
1251 | * delete it. | ||
1252 | */ | ||
1253 | void exofs_delete_inode(struct inode *inode) | ||
1254 | { | ||
1255 | struct exofs_i_info *oi = exofs_i(inode); | ||
1256 | struct super_block *sb = inode->i_sb; | ||
1257 | struct exofs_sb_info *sbi = sb->s_fs_info; | ||
1258 | struct osd_obj_id obj = {sbi->s_pid, inode->i_ino + EXOFS_OBJ_OFF}; | ||
1259 | struct osd_request *or; | ||
1260 | int ret; | ||
1261 | |||
1262 | truncate_inode_pages(&inode->i_data, 0); | ||
1263 | |||
1264 | if (is_bad_inode(inode)) | ||
1265 | goto no_delete; | ||
1266 | |||
1267 | mark_inode_dirty(inode); | ||
1268 | exofs_update_inode(inode, inode_needs_sync(inode)); | ||
1269 | |||
1270 | inode->i_size = 0; | ||
1271 | if (inode->i_blocks) | ||
1272 | exofs_truncate(inode); | ||
1273 | |||
1274 | clear_inode(inode); | ||
1275 | |||
1276 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
1277 | if (unlikely(!or)) { | ||
1278 | EXOFS_ERR("exofs_delete_inode: osd_start_request failed\n"); | ||
1279 | return; | ||
1280 | } | ||
1281 | |||
1282 | osd_req_remove_object(or, &obj); | ||
1283 | |||
1284 | /* if we are deleting an obj that hasn't been created yet, wait */ | ||
1285 | if (!obj_created(oi)) { | ||
1286 | BUG_ON(!obj_2bcreated(oi)); | ||
1287 | wait_event(oi->i_wq, obj_created(oi)); | ||
1288 | } | ||
1289 | |||
1290 | ret = exofs_async_op(or, delete_done, sbi, oi->i_cred); | ||
1291 | if (ret) { | ||
1292 | EXOFS_ERR( | ||
1293 | "ERROR: @exofs_delete_inode exofs_async_op failed\n"); | ||
1294 | osd_end_request(or); | ||
1295 | return; | ||
1296 | } | ||
1297 | atomic_inc(&sbi->s_curr_pending); | ||
1298 | |||
1299 | return; | ||
1300 | |||
1301 | no_delete: | ||
1302 | clear_inode(inode); | ||
1303 | } | ||
diff --git a/fs/exofs/namei.c b/fs/exofs/namei.c new file mode 100644 index 000000000000..77fdd765e76d --- /dev/null +++ b/fs/exofs/namei.c | |||
@@ -0,0 +1,342 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include "exofs.h" | ||
37 | |||
38 | static inline int exofs_add_nondir(struct dentry *dentry, struct inode *inode) | ||
39 | { | ||
40 | int err = exofs_add_link(dentry, inode); | ||
41 | if (!err) { | ||
42 | d_instantiate(dentry, inode); | ||
43 | return 0; | ||
44 | } | ||
45 | inode_dec_link_count(inode); | ||
46 | iput(inode); | ||
47 | return err; | ||
48 | } | ||
49 | |||
50 | static struct dentry *exofs_lookup(struct inode *dir, struct dentry *dentry, | ||
51 | struct nameidata *nd) | ||
52 | { | ||
53 | struct inode *inode; | ||
54 | ino_t ino; | ||
55 | |||
56 | if (dentry->d_name.len > EXOFS_NAME_LEN) | ||
57 | return ERR_PTR(-ENAMETOOLONG); | ||
58 | |||
59 | ino = exofs_inode_by_name(dir, dentry); | ||
60 | inode = NULL; | ||
61 | if (ino) { | ||
62 | inode = exofs_iget(dir->i_sb, ino); | ||
63 | if (IS_ERR(inode)) | ||
64 | return ERR_CAST(inode); | ||
65 | } | ||
66 | return d_splice_alias(inode, dentry); | ||
67 | } | ||
68 | |||
69 | static int exofs_create(struct inode *dir, struct dentry *dentry, int mode, | ||
70 | struct nameidata *nd) | ||
71 | { | ||
72 | struct inode *inode = exofs_new_inode(dir, mode); | ||
73 | int err = PTR_ERR(inode); | ||
74 | if (!IS_ERR(inode)) { | ||
75 | inode->i_op = &exofs_file_inode_operations; | ||
76 | inode->i_fop = &exofs_file_operations; | ||
77 | inode->i_mapping->a_ops = &exofs_aops; | ||
78 | mark_inode_dirty(inode); | ||
79 | err = exofs_add_nondir(dentry, inode); | ||
80 | } | ||
81 | return err; | ||
82 | } | ||
83 | |||
84 | static int exofs_mknod(struct inode *dir, struct dentry *dentry, int mode, | ||
85 | dev_t rdev) | ||
86 | { | ||
87 | struct inode *inode; | ||
88 | int err; | ||
89 | |||
90 | if (!new_valid_dev(rdev)) | ||
91 | return -EINVAL; | ||
92 | |||
93 | inode = exofs_new_inode(dir, mode); | ||
94 | err = PTR_ERR(inode); | ||
95 | if (!IS_ERR(inode)) { | ||
96 | init_special_inode(inode, inode->i_mode, rdev); | ||
97 | mark_inode_dirty(inode); | ||
98 | err = exofs_add_nondir(dentry, inode); | ||
99 | } | ||
100 | return err; | ||
101 | } | ||
102 | |||
103 | static int exofs_symlink(struct inode *dir, struct dentry *dentry, | ||
104 | const char *symname) | ||
105 | { | ||
106 | struct super_block *sb = dir->i_sb; | ||
107 | int err = -ENAMETOOLONG; | ||
108 | unsigned l = strlen(symname)+1; | ||
109 | struct inode *inode; | ||
110 | struct exofs_i_info *oi; | ||
111 | |||
112 | if (l > sb->s_blocksize) | ||
113 | goto out; | ||
114 | |||
115 | inode = exofs_new_inode(dir, S_IFLNK | S_IRWXUGO); | ||
116 | err = PTR_ERR(inode); | ||
117 | if (IS_ERR(inode)) | ||
118 | goto out; | ||
119 | |||
120 | oi = exofs_i(inode); | ||
121 | if (l > sizeof(oi->i_data)) { | ||
122 | /* slow symlink */ | ||
123 | inode->i_op = &exofs_symlink_inode_operations; | ||
124 | inode->i_mapping->a_ops = &exofs_aops; | ||
125 | memset(oi->i_data, 0, sizeof(oi->i_data)); | ||
126 | |||
127 | err = page_symlink(inode, symname, l); | ||
128 | if (err) | ||
129 | goto out_fail; | ||
130 | } else { | ||
131 | /* fast symlink */ | ||
132 | inode->i_op = &exofs_fast_symlink_inode_operations; | ||
133 | memcpy(oi->i_data, symname, l); | ||
134 | inode->i_size = l-1; | ||
135 | } | ||
136 | mark_inode_dirty(inode); | ||
137 | |||
138 | err = exofs_add_nondir(dentry, inode); | ||
139 | out: | ||
140 | return err; | ||
141 | |||
142 | out_fail: | ||
143 | inode_dec_link_count(inode); | ||
144 | iput(inode); | ||
145 | goto out; | ||
146 | } | ||
147 | |||
148 | static int exofs_link(struct dentry *old_dentry, struct inode *dir, | ||
149 | struct dentry *dentry) | ||
150 | { | ||
151 | struct inode *inode = old_dentry->d_inode; | ||
152 | |||
153 | if (inode->i_nlink >= EXOFS_LINK_MAX) | ||
154 | return -EMLINK; | ||
155 | |||
156 | inode->i_ctime = CURRENT_TIME; | ||
157 | inode_inc_link_count(inode); | ||
158 | atomic_inc(&inode->i_count); | ||
159 | |||
160 | return exofs_add_nondir(dentry, inode); | ||
161 | } | ||
162 | |||
163 | static int exofs_mkdir(struct inode *dir, struct dentry *dentry, int mode) | ||
164 | { | ||
165 | struct inode *inode; | ||
166 | int err = -EMLINK; | ||
167 | |||
168 | if (dir->i_nlink >= EXOFS_LINK_MAX) | ||
169 | goto out; | ||
170 | |||
171 | inode_inc_link_count(dir); | ||
172 | |||
173 | inode = exofs_new_inode(dir, S_IFDIR | mode); | ||
174 | err = PTR_ERR(inode); | ||
175 | if (IS_ERR(inode)) | ||
176 | goto out_dir; | ||
177 | |||
178 | inode->i_op = &exofs_dir_inode_operations; | ||
179 | inode->i_fop = &exofs_dir_operations; | ||
180 | inode->i_mapping->a_ops = &exofs_aops; | ||
181 | |||
182 | inode_inc_link_count(inode); | ||
183 | |||
184 | err = exofs_make_empty(inode, dir); | ||
185 | if (err) | ||
186 | goto out_fail; | ||
187 | |||
188 | err = exofs_add_link(dentry, inode); | ||
189 | if (err) | ||
190 | goto out_fail; | ||
191 | |||
192 | d_instantiate(dentry, inode); | ||
193 | out: | ||
194 | return err; | ||
195 | |||
196 | out_fail: | ||
197 | inode_dec_link_count(inode); | ||
198 | inode_dec_link_count(inode); | ||
199 | iput(inode); | ||
200 | out_dir: | ||
201 | inode_dec_link_count(dir); | ||
202 | goto out; | ||
203 | } | ||
204 | |||
205 | static int exofs_unlink(struct inode *dir, struct dentry *dentry) | ||
206 | { | ||
207 | struct inode *inode = dentry->d_inode; | ||
208 | struct exofs_dir_entry *de; | ||
209 | struct page *page; | ||
210 | int err = -ENOENT; | ||
211 | |||
212 | de = exofs_find_entry(dir, dentry, &page); | ||
213 | if (!de) | ||
214 | goto out; | ||
215 | |||
216 | err = exofs_delete_entry(de, page); | ||
217 | if (err) | ||
218 | goto out; | ||
219 | |||
220 | inode->i_ctime = dir->i_ctime; | ||
221 | inode_dec_link_count(inode); | ||
222 | err = 0; | ||
223 | out: | ||
224 | return err; | ||
225 | } | ||
226 | |||
227 | static int exofs_rmdir(struct inode *dir, struct dentry *dentry) | ||
228 | { | ||
229 | struct inode *inode = dentry->d_inode; | ||
230 | int err = -ENOTEMPTY; | ||
231 | |||
232 | if (exofs_empty_dir(inode)) { | ||
233 | err = exofs_unlink(dir, dentry); | ||
234 | if (!err) { | ||
235 | inode->i_size = 0; | ||
236 | inode_dec_link_count(inode); | ||
237 | inode_dec_link_count(dir); | ||
238 | } | ||
239 | } | ||
240 | return err; | ||
241 | } | ||
242 | |||
243 | static int exofs_rename(struct inode *old_dir, struct dentry *old_dentry, | ||
244 | struct inode *new_dir, struct dentry *new_dentry) | ||
245 | { | ||
246 | struct inode *old_inode = old_dentry->d_inode; | ||
247 | struct inode *new_inode = new_dentry->d_inode; | ||
248 | struct page *dir_page = NULL; | ||
249 | struct exofs_dir_entry *dir_de = NULL; | ||
250 | struct page *old_page; | ||
251 | struct exofs_dir_entry *old_de; | ||
252 | int err = -ENOENT; | ||
253 | |||
254 | old_de = exofs_find_entry(old_dir, old_dentry, &old_page); | ||
255 | if (!old_de) | ||
256 | goto out; | ||
257 | |||
258 | if (S_ISDIR(old_inode->i_mode)) { | ||
259 | err = -EIO; | ||
260 | dir_de = exofs_dotdot(old_inode, &dir_page); | ||
261 | if (!dir_de) | ||
262 | goto out_old; | ||
263 | } | ||
264 | |||
265 | if (new_inode) { | ||
266 | struct page *new_page; | ||
267 | struct exofs_dir_entry *new_de; | ||
268 | |||
269 | err = -ENOTEMPTY; | ||
270 | if (dir_de && !exofs_empty_dir(new_inode)) | ||
271 | goto out_dir; | ||
272 | |||
273 | err = -ENOENT; | ||
274 | new_de = exofs_find_entry(new_dir, new_dentry, &new_page); | ||
275 | if (!new_de) | ||
276 | goto out_dir; | ||
277 | inode_inc_link_count(old_inode); | ||
278 | err = exofs_set_link(new_dir, new_de, new_page, old_inode); | ||
279 | new_inode->i_ctime = CURRENT_TIME; | ||
280 | if (dir_de) | ||
281 | drop_nlink(new_inode); | ||
282 | inode_dec_link_count(new_inode); | ||
283 | if (err) | ||
284 | goto out_dir; | ||
285 | } else { | ||
286 | if (dir_de) { | ||
287 | err = -EMLINK; | ||
288 | if (new_dir->i_nlink >= EXOFS_LINK_MAX) | ||
289 | goto out_dir; | ||
290 | } | ||
291 | inode_inc_link_count(old_inode); | ||
292 | err = exofs_add_link(new_dentry, old_inode); | ||
293 | if (err) { | ||
294 | inode_dec_link_count(old_inode); | ||
295 | goto out_dir; | ||
296 | } | ||
297 | if (dir_de) | ||
298 | inode_inc_link_count(new_dir); | ||
299 | } | ||
300 | |||
301 | old_inode->i_ctime = CURRENT_TIME; | ||
302 | |||
303 | exofs_delete_entry(old_de, old_page); | ||
304 | inode_dec_link_count(old_inode); | ||
305 | |||
306 | if (dir_de) { | ||
307 | err = exofs_set_link(old_inode, dir_de, dir_page, new_dir); | ||
308 | inode_dec_link_count(old_dir); | ||
309 | if (err) | ||
310 | goto out_dir; | ||
311 | } | ||
312 | return 0; | ||
313 | |||
314 | |||
315 | out_dir: | ||
316 | if (dir_de) { | ||
317 | kunmap(dir_page); | ||
318 | page_cache_release(dir_page); | ||
319 | } | ||
320 | out_old: | ||
321 | kunmap(old_page); | ||
322 | page_cache_release(old_page); | ||
323 | out: | ||
324 | return err; | ||
325 | } | ||
326 | |||
327 | const struct inode_operations exofs_dir_inode_operations = { | ||
328 | .create = exofs_create, | ||
329 | .lookup = exofs_lookup, | ||
330 | .link = exofs_link, | ||
331 | .unlink = exofs_unlink, | ||
332 | .symlink = exofs_symlink, | ||
333 | .mkdir = exofs_mkdir, | ||
334 | .rmdir = exofs_rmdir, | ||
335 | .mknod = exofs_mknod, | ||
336 | .rename = exofs_rename, | ||
337 | .setattr = exofs_setattr, | ||
338 | }; | ||
339 | |||
340 | const struct inode_operations exofs_special_inode_operations = { | ||
341 | .setattr = exofs_setattr, | ||
342 | }; | ||
diff --git a/fs/exofs/osd.c b/fs/exofs/osd.c new file mode 100644 index 000000000000..b249ae97fb15 --- /dev/null +++ b/fs/exofs/osd.c | |||
@@ -0,0 +1,153 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * This file is part of exofs. | ||
10 | * | ||
11 | * exofs is free software; you can redistribute it and/or modify | ||
12 | * it under the terms of the GNU General Public License as published by | ||
13 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
14 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
15 | * version of GPL for exofs is version 2. | ||
16 | * | ||
17 | * exofs is distributed in the hope that it will be useful, | ||
18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
20 | * GNU General Public License for more details. | ||
21 | * | ||
22 | * You should have received a copy of the GNU General Public License | ||
23 | * along with exofs; if not, write to the Free Software | ||
24 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
25 | */ | ||
26 | |||
27 | #include <scsi/scsi_device.h> | ||
28 | #include <scsi/osd_sense.h> | ||
29 | |||
30 | #include "exofs.h" | ||
31 | |||
32 | int exofs_check_ok_resid(struct osd_request *or, u64 *in_resid, u64 *out_resid) | ||
33 | { | ||
34 | struct osd_sense_info osi; | ||
35 | int ret = osd_req_decode_sense(or, &osi); | ||
36 | |||
37 | if (ret) { /* translate to Linux codes */ | ||
38 | if (osi.additional_code == scsi_invalid_field_in_cdb) { | ||
39 | if (osi.cdb_field_offset == OSD_CFO_STARTING_BYTE) | ||
40 | ret = -EFAULT; | ||
41 | if (osi.cdb_field_offset == OSD_CFO_OBJECT_ID) | ||
42 | ret = -ENOENT; | ||
43 | else | ||
44 | ret = -EINVAL; | ||
45 | } else if (osi.additional_code == osd_quota_error) | ||
46 | ret = -ENOSPC; | ||
47 | else | ||
48 | ret = -EIO; | ||
49 | } | ||
50 | |||
51 | /* FIXME: should be include in osd_sense_info */ | ||
52 | if (in_resid) | ||
53 | *in_resid = or->in.req ? or->in.req->data_len : 0; | ||
54 | |||
55 | if (out_resid) | ||
56 | *out_resid = or->out.req ? or->out.req->data_len : 0; | ||
57 | |||
58 | return ret; | ||
59 | } | ||
60 | |||
61 | void exofs_make_credential(u8 cred_a[OSD_CAP_LEN], const struct osd_obj_id *obj) | ||
62 | { | ||
63 | osd_sec_init_nosec_doall_caps(cred_a, obj, false, true); | ||
64 | } | ||
65 | |||
66 | /* | ||
67 | * Perform a synchronous OSD operation. | ||
68 | */ | ||
69 | int exofs_sync_op(struct osd_request *or, int timeout, uint8_t *credential) | ||
70 | { | ||
71 | int ret; | ||
72 | |||
73 | or->timeout = timeout; | ||
74 | ret = osd_finalize_request(or, 0, credential, NULL); | ||
75 | if (ret) { | ||
76 | EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret); | ||
77 | return ret; | ||
78 | } | ||
79 | |||
80 | ret = osd_execute_request(or); | ||
81 | |||
82 | if (ret) | ||
83 | EXOFS_DBGMSG("osd_execute_request() => %d\n", ret); | ||
84 | /* osd_req_decode_sense(or, ret); */ | ||
85 | return ret; | ||
86 | } | ||
87 | |||
88 | /* | ||
89 | * Perform an asynchronous OSD operation. | ||
90 | */ | ||
91 | int exofs_async_op(struct osd_request *or, osd_req_done_fn *async_done, | ||
92 | void *caller_context, u8 *cred) | ||
93 | { | ||
94 | int ret; | ||
95 | |||
96 | ret = osd_finalize_request(or, 0, cred, NULL); | ||
97 | if (ret) { | ||
98 | EXOFS_DBGMSG("Faild to osd_finalize_request() => %d\n", ret); | ||
99 | return ret; | ||
100 | } | ||
101 | |||
102 | ret = osd_execute_request_async(or, async_done, caller_context); | ||
103 | |||
104 | if (ret) | ||
105 | EXOFS_DBGMSG("osd_execute_request_async() => %d\n", ret); | ||
106 | return ret; | ||
107 | } | ||
108 | |||
109 | int extract_attr_from_req(struct osd_request *or, struct osd_attr *attr) | ||
110 | { | ||
111 | struct osd_attr cur_attr = {.attr_page = 0}; /* start with zeros */ | ||
112 | void *iter = NULL; | ||
113 | int nelem; | ||
114 | |||
115 | do { | ||
116 | nelem = 1; | ||
117 | osd_req_decode_get_attr_list(or, &cur_attr, &nelem, &iter); | ||
118 | if ((cur_attr.attr_page == attr->attr_page) && | ||
119 | (cur_attr.attr_id == attr->attr_id)) { | ||
120 | attr->len = cur_attr.len; | ||
121 | attr->val_ptr = cur_attr.val_ptr; | ||
122 | return 0; | ||
123 | } | ||
124 | } while (iter); | ||
125 | |||
126 | return -EIO; | ||
127 | } | ||
128 | |||
129 | int osd_req_read_kern(struct osd_request *or, | ||
130 | const struct osd_obj_id *obj, u64 offset, void* buff, u64 len) | ||
131 | { | ||
132 | struct request_queue *req_q = or->osd_dev->scsi_device->request_queue; | ||
133 | struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL); | ||
134 | |||
135 | if (!bio) | ||
136 | return -ENOMEM; | ||
137 | |||
138 | osd_req_read(or, obj, bio, offset); | ||
139 | return 0; | ||
140 | } | ||
141 | |||
142 | int osd_req_write_kern(struct osd_request *or, | ||
143 | const struct osd_obj_id *obj, u64 offset, void* buff, u64 len) | ||
144 | { | ||
145 | struct request_queue *req_q = or->osd_dev->scsi_device->request_queue; | ||
146 | struct bio *bio = bio_map_kern(req_q, buff, len, GFP_KERNEL); | ||
147 | |||
148 | if (!bio) | ||
149 | return -ENOMEM; | ||
150 | |||
151 | osd_req_write(or, obj, bio, offset); | ||
152 | return 0; | ||
153 | } | ||
diff --git a/fs/exofs/super.c b/fs/exofs/super.c new file mode 100644 index 000000000000..9f1985e857e2 --- /dev/null +++ b/fs/exofs/super.c | |||
@@ -0,0 +1,584 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/string.h> | ||
37 | #include <linux/parser.h> | ||
38 | #include <linux/vfs.h> | ||
39 | #include <linux/random.h> | ||
40 | #include <linux/exportfs.h> | ||
41 | |||
42 | #include "exofs.h" | ||
43 | |||
44 | /****************************************************************************** | ||
45 | * MOUNT OPTIONS | ||
46 | *****************************************************************************/ | ||
47 | |||
48 | /* | ||
49 | * struct to hold what we get from mount options | ||
50 | */ | ||
51 | struct exofs_mountopt { | ||
52 | const char *dev_name; | ||
53 | uint64_t pid; | ||
54 | int timeout; | ||
55 | }; | ||
56 | |||
57 | /* | ||
58 | * exofs-specific mount-time options. | ||
59 | */ | ||
60 | enum { Opt_pid, Opt_to, Opt_mkfs, Opt_format, Opt_err }; | ||
61 | |||
62 | /* | ||
63 | * Our mount-time options. These should ideally be 64-bit unsigned, but the | ||
64 | * kernel's parsing functions do not currently support that. 32-bit should be | ||
65 | * sufficient for most applications now. | ||
66 | */ | ||
67 | static match_table_t tokens = { | ||
68 | {Opt_pid, "pid=%u"}, | ||
69 | {Opt_to, "to=%u"}, | ||
70 | {Opt_err, NULL} | ||
71 | }; | ||
72 | |||
73 | /* | ||
74 | * The main option parsing method. Also makes sure that all of the mandatory | ||
75 | * mount options were set. | ||
76 | */ | ||
77 | static int parse_options(char *options, struct exofs_mountopt *opts) | ||
78 | { | ||
79 | char *p; | ||
80 | substring_t args[MAX_OPT_ARGS]; | ||
81 | int option; | ||
82 | bool s_pid = false; | ||
83 | |||
84 | EXOFS_DBGMSG("parse_options %s\n", options); | ||
85 | /* defaults */ | ||
86 | memset(opts, 0, sizeof(*opts)); | ||
87 | opts->timeout = BLK_DEFAULT_SG_TIMEOUT; | ||
88 | |||
89 | while ((p = strsep(&options, ",")) != NULL) { | ||
90 | int token; | ||
91 | char str[32]; | ||
92 | |||
93 | if (!*p) | ||
94 | continue; | ||
95 | |||
96 | token = match_token(p, tokens, args); | ||
97 | switch (token) { | ||
98 | case Opt_pid: | ||
99 | if (0 == match_strlcpy(str, &args[0], sizeof(str))) | ||
100 | return -EINVAL; | ||
101 | opts->pid = simple_strtoull(str, NULL, 0); | ||
102 | if (opts->pid < EXOFS_MIN_PID) { | ||
103 | EXOFS_ERR("Partition ID must be >= %u", | ||
104 | EXOFS_MIN_PID); | ||
105 | return -EINVAL; | ||
106 | } | ||
107 | s_pid = 1; | ||
108 | break; | ||
109 | case Opt_to: | ||
110 | if (match_int(&args[0], &option)) | ||
111 | return -EINVAL; | ||
112 | if (option <= 0) { | ||
113 | EXOFS_ERR("Timout must be > 0"); | ||
114 | return -EINVAL; | ||
115 | } | ||
116 | opts->timeout = option * HZ; | ||
117 | break; | ||
118 | } | ||
119 | } | ||
120 | |||
121 | if (!s_pid) { | ||
122 | EXOFS_ERR("Need to specify the following options:\n"); | ||
123 | EXOFS_ERR(" -o pid=pid_no_to_use\n"); | ||
124 | return -EINVAL; | ||
125 | } | ||
126 | |||
127 | return 0; | ||
128 | } | ||
129 | |||
130 | /****************************************************************************** | ||
131 | * INODE CACHE | ||
132 | *****************************************************************************/ | ||
133 | |||
134 | /* | ||
135 | * Our inode cache. Isn't it pretty? | ||
136 | */ | ||
137 | static struct kmem_cache *exofs_inode_cachep; | ||
138 | |||
139 | /* | ||
140 | * Allocate an inode in the cache | ||
141 | */ | ||
142 | static struct inode *exofs_alloc_inode(struct super_block *sb) | ||
143 | { | ||
144 | struct exofs_i_info *oi; | ||
145 | |||
146 | oi = kmem_cache_alloc(exofs_inode_cachep, GFP_KERNEL); | ||
147 | if (!oi) | ||
148 | return NULL; | ||
149 | |||
150 | oi->vfs_inode.i_version = 1; | ||
151 | return &oi->vfs_inode; | ||
152 | } | ||
153 | |||
154 | /* | ||
155 | * Remove an inode from the cache | ||
156 | */ | ||
157 | static void exofs_destroy_inode(struct inode *inode) | ||
158 | { | ||
159 | kmem_cache_free(exofs_inode_cachep, exofs_i(inode)); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * Initialize the inode | ||
164 | */ | ||
165 | static void exofs_init_once(void *foo) | ||
166 | { | ||
167 | struct exofs_i_info *oi = foo; | ||
168 | |||
169 | inode_init_once(&oi->vfs_inode); | ||
170 | } | ||
171 | |||
172 | /* | ||
173 | * Create and initialize the inode cache | ||
174 | */ | ||
175 | static int init_inodecache(void) | ||
176 | { | ||
177 | exofs_inode_cachep = kmem_cache_create("exofs_inode_cache", | ||
178 | sizeof(struct exofs_i_info), 0, | ||
179 | SLAB_RECLAIM_ACCOUNT | SLAB_MEM_SPREAD, | ||
180 | exofs_init_once); | ||
181 | if (exofs_inode_cachep == NULL) | ||
182 | return -ENOMEM; | ||
183 | return 0; | ||
184 | } | ||
185 | |||
186 | /* | ||
187 | * Destroy the inode cache | ||
188 | */ | ||
189 | static void destroy_inodecache(void) | ||
190 | { | ||
191 | kmem_cache_destroy(exofs_inode_cachep); | ||
192 | } | ||
193 | |||
194 | /****************************************************************************** | ||
195 | * SUPERBLOCK FUNCTIONS | ||
196 | *****************************************************************************/ | ||
197 | static const struct super_operations exofs_sops; | ||
198 | static const struct export_operations exofs_export_ops; | ||
199 | |||
200 | /* | ||
201 | * Write the superblock to the OSD | ||
202 | */ | ||
203 | static void exofs_write_super(struct super_block *sb) | ||
204 | { | ||
205 | struct exofs_sb_info *sbi; | ||
206 | struct exofs_fscb *fscb; | ||
207 | struct osd_request *or; | ||
208 | struct osd_obj_id obj; | ||
209 | int ret; | ||
210 | |||
211 | fscb = kzalloc(sizeof(struct exofs_fscb), GFP_KERNEL); | ||
212 | if (!fscb) { | ||
213 | EXOFS_ERR("exofs_write_super: memory allocation failed.\n"); | ||
214 | return; | ||
215 | } | ||
216 | |||
217 | lock_kernel(); | ||
218 | sbi = sb->s_fs_info; | ||
219 | fscb->s_nextid = cpu_to_le64(sbi->s_nextid); | ||
220 | fscb->s_numfiles = cpu_to_le32(sbi->s_numfiles); | ||
221 | fscb->s_magic = cpu_to_le16(sb->s_magic); | ||
222 | fscb->s_newfs = 0; | ||
223 | |||
224 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
225 | if (unlikely(!or)) { | ||
226 | EXOFS_ERR("exofs_write_super: osd_start_request failed.\n"); | ||
227 | goto out; | ||
228 | } | ||
229 | |||
230 | obj.partition = sbi->s_pid; | ||
231 | obj.id = EXOFS_SUPER_ID; | ||
232 | ret = osd_req_write_kern(or, &obj, 0, fscb, sizeof(*fscb)); | ||
233 | if (unlikely(ret)) { | ||
234 | EXOFS_ERR("exofs_write_super: osd_req_write_kern failed.\n"); | ||
235 | goto out; | ||
236 | } | ||
237 | |||
238 | ret = exofs_sync_op(or, sbi->s_timeout, sbi->s_cred); | ||
239 | if (unlikely(ret)) { | ||
240 | EXOFS_ERR("exofs_write_super: exofs_sync_op failed.\n"); | ||
241 | goto out; | ||
242 | } | ||
243 | sb->s_dirt = 0; | ||
244 | |||
245 | out: | ||
246 | if (or) | ||
247 | osd_end_request(or); | ||
248 | unlock_kernel(); | ||
249 | kfree(fscb); | ||
250 | } | ||
251 | |||
252 | /* | ||
253 | * This function is called when the vfs is freeing the superblock. We just | ||
254 | * need to free our own part. | ||
255 | */ | ||
256 | static void exofs_put_super(struct super_block *sb) | ||
257 | { | ||
258 | int num_pend; | ||
259 | struct exofs_sb_info *sbi = sb->s_fs_info; | ||
260 | |||
261 | /* make sure there are no pending commands */ | ||
262 | for (num_pend = atomic_read(&sbi->s_curr_pending); num_pend > 0; | ||
263 | num_pend = atomic_read(&sbi->s_curr_pending)) { | ||
264 | wait_queue_head_t wq; | ||
265 | init_waitqueue_head(&wq); | ||
266 | wait_event_timeout(wq, | ||
267 | (atomic_read(&sbi->s_curr_pending) == 0), | ||
268 | msecs_to_jiffies(100)); | ||
269 | } | ||
270 | |||
271 | osduld_put_device(sbi->s_dev); | ||
272 | kfree(sb->s_fs_info); | ||
273 | sb->s_fs_info = NULL; | ||
274 | } | ||
275 | |||
276 | /* | ||
277 | * Read the superblock from the OSD and fill in the fields | ||
278 | */ | ||
279 | static int exofs_fill_super(struct super_block *sb, void *data, int silent) | ||
280 | { | ||
281 | struct inode *root; | ||
282 | struct exofs_mountopt *opts = data; | ||
283 | struct exofs_sb_info *sbi; /*extended info */ | ||
284 | struct exofs_fscb fscb; /*on-disk superblock info */ | ||
285 | struct osd_request *or = NULL; | ||
286 | struct osd_obj_id obj; | ||
287 | int ret; | ||
288 | |||
289 | sbi = kzalloc(sizeof(*sbi), GFP_KERNEL); | ||
290 | if (!sbi) | ||
291 | return -ENOMEM; | ||
292 | sb->s_fs_info = sbi; | ||
293 | |||
294 | /* use mount options to fill superblock */ | ||
295 | sbi->s_dev = osduld_path_lookup(opts->dev_name); | ||
296 | if (IS_ERR(sbi->s_dev)) { | ||
297 | ret = PTR_ERR(sbi->s_dev); | ||
298 | sbi->s_dev = NULL; | ||
299 | goto free_sbi; | ||
300 | } | ||
301 | |||
302 | sbi->s_pid = opts->pid; | ||
303 | sbi->s_timeout = opts->timeout; | ||
304 | |||
305 | /* fill in some other data by hand */ | ||
306 | memset(sb->s_id, 0, sizeof(sb->s_id)); | ||
307 | strcpy(sb->s_id, "exofs"); | ||
308 | sb->s_blocksize = EXOFS_BLKSIZE; | ||
309 | sb->s_blocksize_bits = EXOFS_BLKSHIFT; | ||
310 | sb->s_maxbytes = MAX_LFS_FILESIZE; | ||
311 | atomic_set(&sbi->s_curr_pending, 0); | ||
312 | sb->s_bdev = NULL; | ||
313 | sb->s_dev = 0; | ||
314 | |||
315 | /* read data from on-disk superblock object */ | ||
316 | obj.partition = sbi->s_pid; | ||
317 | obj.id = EXOFS_SUPER_ID; | ||
318 | exofs_make_credential(sbi->s_cred, &obj); | ||
319 | |||
320 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
321 | if (unlikely(!or)) { | ||
322 | if (!silent) | ||
323 | EXOFS_ERR( | ||
324 | "exofs_fill_super: osd_start_request failed.\n"); | ||
325 | ret = -ENOMEM; | ||
326 | goto free_sbi; | ||
327 | } | ||
328 | ret = osd_req_read_kern(or, &obj, 0, &fscb, sizeof(fscb)); | ||
329 | if (unlikely(ret)) { | ||
330 | if (!silent) | ||
331 | EXOFS_ERR( | ||
332 | "exofs_fill_super: osd_req_read_kern failed.\n"); | ||
333 | ret = -ENOMEM; | ||
334 | goto free_sbi; | ||
335 | } | ||
336 | |||
337 | ret = exofs_sync_op(or, sbi->s_timeout, sbi->s_cred); | ||
338 | if (unlikely(ret)) { | ||
339 | if (!silent) | ||
340 | EXOFS_ERR("exofs_fill_super: exofs_sync_op failed.\n"); | ||
341 | ret = -EIO; | ||
342 | goto free_sbi; | ||
343 | } | ||
344 | |||
345 | sb->s_magic = le16_to_cpu(fscb.s_magic); | ||
346 | sbi->s_nextid = le64_to_cpu(fscb.s_nextid); | ||
347 | sbi->s_numfiles = le32_to_cpu(fscb.s_numfiles); | ||
348 | |||
349 | /* make sure what we read from the object store is correct */ | ||
350 | if (sb->s_magic != EXOFS_SUPER_MAGIC) { | ||
351 | if (!silent) | ||
352 | EXOFS_ERR("ERROR: Bad magic value\n"); | ||
353 | ret = -EINVAL; | ||
354 | goto free_sbi; | ||
355 | } | ||
356 | |||
357 | /* start generation numbers from a random point */ | ||
358 | get_random_bytes(&sbi->s_next_generation, sizeof(u32)); | ||
359 | spin_lock_init(&sbi->s_next_gen_lock); | ||
360 | |||
361 | /* set up operation vectors */ | ||
362 | sb->s_op = &exofs_sops; | ||
363 | sb->s_export_op = &exofs_export_ops; | ||
364 | root = exofs_iget(sb, EXOFS_ROOT_ID - EXOFS_OBJ_OFF); | ||
365 | if (IS_ERR(root)) { | ||
366 | EXOFS_ERR("ERROR: exofs_iget failed\n"); | ||
367 | ret = PTR_ERR(root); | ||
368 | goto free_sbi; | ||
369 | } | ||
370 | sb->s_root = d_alloc_root(root); | ||
371 | if (!sb->s_root) { | ||
372 | iput(root); | ||
373 | EXOFS_ERR("ERROR: get root inode failed\n"); | ||
374 | ret = -ENOMEM; | ||
375 | goto free_sbi; | ||
376 | } | ||
377 | |||
378 | if (!S_ISDIR(root->i_mode)) { | ||
379 | dput(sb->s_root); | ||
380 | sb->s_root = NULL; | ||
381 | EXOFS_ERR("ERROR: corrupt root inode (mode = %hd)\n", | ||
382 | root->i_mode); | ||
383 | ret = -EINVAL; | ||
384 | goto free_sbi; | ||
385 | } | ||
386 | |||
387 | ret = 0; | ||
388 | out: | ||
389 | if (or) | ||
390 | osd_end_request(or); | ||
391 | return ret; | ||
392 | |||
393 | free_sbi: | ||
394 | osduld_put_device(sbi->s_dev); /* NULL safe */ | ||
395 | kfree(sbi); | ||
396 | goto out; | ||
397 | } | ||
398 | |||
399 | /* | ||
400 | * Set up the superblock (calls exofs_fill_super eventually) | ||
401 | */ | ||
402 | static int exofs_get_sb(struct file_system_type *type, | ||
403 | int flags, const char *dev_name, | ||
404 | void *data, struct vfsmount *mnt) | ||
405 | { | ||
406 | struct exofs_mountopt opts; | ||
407 | int ret; | ||
408 | |||
409 | ret = parse_options(data, &opts); | ||
410 | if (ret) | ||
411 | return ret; | ||
412 | |||
413 | opts.dev_name = dev_name; | ||
414 | return get_sb_nodev(type, flags, &opts, exofs_fill_super, mnt); | ||
415 | } | ||
416 | |||
417 | /* | ||
418 | * Return information about the file system state in the buffer. This is used | ||
419 | * by the 'df' command, for example. | ||
420 | */ | ||
421 | static int exofs_statfs(struct dentry *dentry, struct kstatfs *buf) | ||
422 | { | ||
423 | struct super_block *sb = dentry->d_sb; | ||
424 | struct exofs_sb_info *sbi = sb->s_fs_info; | ||
425 | struct osd_obj_id obj = {sbi->s_pid, 0}; | ||
426 | struct osd_attr attrs[] = { | ||
427 | ATTR_DEF(OSD_APAGE_PARTITION_QUOTAS, | ||
428 | OSD_ATTR_PQ_CAPACITY_QUOTA, sizeof(__be64)), | ||
429 | ATTR_DEF(OSD_APAGE_PARTITION_INFORMATION, | ||
430 | OSD_ATTR_PI_USED_CAPACITY, sizeof(__be64)), | ||
431 | }; | ||
432 | uint64_t capacity = ULLONG_MAX; | ||
433 | uint64_t used = ULLONG_MAX; | ||
434 | struct osd_request *or; | ||
435 | uint8_t cred_a[OSD_CAP_LEN]; | ||
436 | int ret; | ||
437 | |||
438 | /* get used/capacity attributes */ | ||
439 | exofs_make_credential(cred_a, &obj); | ||
440 | |||
441 | or = osd_start_request(sbi->s_dev, GFP_KERNEL); | ||
442 | if (unlikely(!or)) { | ||
443 | EXOFS_DBGMSG("exofs_statfs: osd_start_request failed.\n"); | ||
444 | return -ENOMEM; | ||
445 | } | ||
446 | |||
447 | osd_req_get_attributes(or, &obj); | ||
448 | osd_req_add_get_attr_list(or, attrs, ARRAY_SIZE(attrs)); | ||
449 | ret = exofs_sync_op(or, sbi->s_timeout, cred_a); | ||
450 | if (unlikely(ret)) | ||
451 | goto out; | ||
452 | |||
453 | ret = extract_attr_from_req(or, &attrs[0]); | ||
454 | if (likely(!ret)) | ||
455 | capacity = get_unaligned_be64(attrs[0].val_ptr); | ||
456 | else | ||
457 | EXOFS_DBGMSG("exofs_statfs: get capacity failed.\n"); | ||
458 | |||
459 | ret = extract_attr_from_req(or, &attrs[1]); | ||
460 | if (likely(!ret)) | ||
461 | used = get_unaligned_be64(attrs[1].val_ptr); | ||
462 | else | ||
463 | EXOFS_DBGMSG("exofs_statfs: get used-space failed.\n"); | ||
464 | |||
465 | /* fill in the stats buffer */ | ||
466 | buf->f_type = EXOFS_SUPER_MAGIC; | ||
467 | buf->f_bsize = EXOFS_BLKSIZE; | ||
468 | buf->f_blocks = (capacity >> EXOFS_BLKSHIFT); | ||
469 | buf->f_bfree = ((capacity - used) >> EXOFS_BLKSHIFT); | ||
470 | buf->f_bavail = buf->f_bfree; | ||
471 | buf->f_files = sbi->s_numfiles; | ||
472 | buf->f_ffree = EXOFS_MAX_ID - sbi->s_numfiles; | ||
473 | buf->f_namelen = EXOFS_NAME_LEN; | ||
474 | |||
475 | out: | ||
476 | osd_end_request(or); | ||
477 | return ret; | ||
478 | } | ||
479 | |||
480 | static const struct super_operations exofs_sops = { | ||
481 | .alloc_inode = exofs_alloc_inode, | ||
482 | .destroy_inode = exofs_destroy_inode, | ||
483 | .write_inode = exofs_write_inode, | ||
484 | .delete_inode = exofs_delete_inode, | ||
485 | .put_super = exofs_put_super, | ||
486 | .write_super = exofs_write_super, | ||
487 | .statfs = exofs_statfs, | ||
488 | }; | ||
489 | |||
490 | /****************************************************************************** | ||
491 | * EXPORT OPERATIONS | ||
492 | *****************************************************************************/ | ||
493 | |||
494 | struct dentry *exofs_get_parent(struct dentry *child) | ||
495 | { | ||
496 | unsigned long ino = exofs_parent_ino(child); | ||
497 | |||
498 | if (!ino) | ||
499 | return NULL; | ||
500 | |||
501 | return d_obtain_alias(exofs_iget(child->d_inode->i_sb, ino)); | ||
502 | } | ||
503 | |||
504 | static struct inode *exofs_nfs_get_inode(struct super_block *sb, | ||
505 | u64 ino, u32 generation) | ||
506 | { | ||
507 | struct inode *inode; | ||
508 | |||
509 | inode = exofs_iget(sb, ino); | ||
510 | if (IS_ERR(inode)) | ||
511 | return ERR_CAST(inode); | ||
512 | if (generation && inode->i_generation != generation) { | ||
513 | /* we didn't find the right inode.. */ | ||
514 | iput(inode); | ||
515 | return ERR_PTR(-ESTALE); | ||
516 | } | ||
517 | return inode; | ||
518 | } | ||
519 | |||
520 | static struct dentry *exofs_fh_to_dentry(struct super_block *sb, | ||
521 | struct fid *fid, int fh_len, int fh_type) | ||
522 | { | ||
523 | return generic_fh_to_dentry(sb, fid, fh_len, fh_type, | ||
524 | exofs_nfs_get_inode); | ||
525 | } | ||
526 | |||
527 | static struct dentry *exofs_fh_to_parent(struct super_block *sb, | ||
528 | struct fid *fid, int fh_len, int fh_type) | ||
529 | { | ||
530 | return generic_fh_to_parent(sb, fid, fh_len, fh_type, | ||
531 | exofs_nfs_get_inode); | ||
532 | } | ||
533 | |||
534 | static const struct export_operations exofs_export_ops = { | ||
535 | .fh_to_dentry = exofs_fh_to_dentry, | ||
536 | .fh_to_parent = exofs_fh_to_parent, | ||
537 | .get_parent = exofs_get_parent, | ||
538 | }; | ||
539 | |||
540 | /****************************************************************************** | ||
541 | * INSMOD/RMMOD | ||
542 | *****************************************************************************/ | ||
543 | |||
544 | /* | ||
545 | * struct that describes this file system | ||
546 | */ | ||
547 | static struct file_system_type exofs_type = { | ||
548 | .owner = THIS_MODULE, | ||
549 | .name = "exofs", | ||
550 | .get_sb = exofs_get_sb, | ||
551 | .kill_sb = generic_shutdown_super, | ||
552 | }; | ||
553 | |||
554 | static int __init init_exofs(void) | ||
555 | { | ||
556 | int err; | ||
557 | |||
558 | err = init_inodecache(); | ||
559 | if (err) | ||
560 | goto out; | ||
561 | |||
562 | err = register_filesystem(&exofs_type); | ||
563 | if (err) | ||
564 | goto out_d; | ||
565 | |||
566 | return 0; | ||
567 | out_d: | ||
568 | destroy_inodecache(); | ||
569 | out: | ||
570 | return err; | ||
571 | } | ||
572 | |||
573 | static void __exit exit_exofs(void) | ||
574 | { | ||
575 | unregister_filesystem(&exofs_type); | ||
576 | destroy_inodecache(); | ||
577 | } | ||
578 | |||
579 | MODULE_AUTHOR("Avishay Traeger <avishay@gmail.com>"); | ||
580 | MODULE_DESCRIPTION("exofs"); | ||
581 | MODULE_LICENSE("GPL"); | ||
582 | |||
583 | module_init(init_exofs) | ||
584 | module_exit(exit_exofs) | ||
diff --git a/fs/exofs/symlink.c b/fs/exofs/symlink.c new file mode 100644 index 000000000000..36e2d7bc7f7b --- /dev/null +++ b/fs/exofs/symlink.c | |||
@@ -0,0 +1,57 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2005, 2006 | ||
3 | * Avishay Traeger (avishay@gmail.com) (avishay@il.ibm.com) | ||
4 | * Copyright (C) 2005, 2006 | ||
5 | * International Business Machines | ||
6 | * Copyright (C) 2008, 2009 | ||
7 | * Boaz Harrosh <bharrosh@panasas.com> | ||
8 | * | ||
9 | * Copyrights for code taken from ext2: | ||
10 | * Copyright (C) 1992, 1993, 1994, 1995 | ||
11 | * Remy Card (card@masi.ibp.fr) | ||
12 | * Laboratoire MASI - Institut Blaise Pascal | ||
13 | * Universite Pierre et Marie Curie (Paris VI) | ||
14 | * from | ||
15 | * linux/fs/minix/inode.c | ||
16 | * Copyright (C) 1991, 1992 Linus Torvalds | ||
17 | * | ||
18 | * This file is part of exofs. | ||
19 | * | ||
20 | * exofs is free software; you can redistribute it and/or modify | ||
21 | * it under the terms of the GNU General Public License as published by | ||
22 | * the Free Software Foundation. Since it is based on ext2, and the only | ||
23 | * valid version of GPL for the Linux kernel is version 2, the only valid | ||
24 | * version of GPL for exofs is version 2. | ||
25 | * | ||
26 | * exofs is distributed in the hope that it will be useful, | ||
27 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
28 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
29 | * GNU General Public License for more details. | ||
30 | * | ||
31 | * You should have received a copy of the GNU General Public License | ||
32 | * along with exofs; if not, write to the Free Software | ||
33 | * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
34 | */ | ||
35 | |||
36 | #include <linux/namei.h> | ||
37 | |||
38 | #include "exofs.h" | ||
39 | |||
40 | static void *exofs_follow_link(struct dentry *dentry, struct nameidata *nd) | ||
41 | { | ||
42 | struct exofs_i_info *oi = exofs_i(dentry->d_inode); | ||
43 | |||
44 | nd_set_link(nd, (char *)oi->i_data); | ||
45 | return NULL; | ||
46 | } | ||
47 | |||
48 | const struct inode_operations exofs_symlink_inode_operations = { | ||
49 | .readlink = generic_readlink, | ||
50 | .follow_link = page_follow_link_light, | ||
51 | .put_link = page_put_link, | ||
52 | }; | ||
53 | |||
54 | const struct inode_operations exofs_fast_symlink_inode_operations = { | ||
55 | .readlink = generic_readlink, | ||
56 | .follow_link = exofs_follow_link, | ||
57 | }; | ||
diff --git a/fs/udf/balloc.c b/fs/udf/balloc.c index 2bb788a2acb1..e48e9a3af763 100644 --- a/fs/udf/balloc.c +++ b/fs/udf/balloc.c | |||
@@ -87,12 +87,12 @@ static int read_block_bitmap(struct super_block *sb, | |||
87 | { | 87 | { |
88 | struct buffer_head *bh = NULL; | 88 | struct buffer_head *bh = NULL; |
89 | int retval = 0; | 89 | int retval = 0; |
90 | kernel_lb_addr loc; | 90 | struct kernel_lb_addr loc; |
91 | 91 | ||
92 | loc.logicalBlockNum = bitmap->s_extPosition; | 92 | loc.logicalBlockNum = bitmap->s_extPosition; |
93 | loc.partitionReferenceNum = UDF_SB(sb)->s_partition; | 93 | loc.partitionReferenceNum = UDF_SB(sb)->s_partition; |
94 | 94 | ||
95 | bh = udf_tread(sb, udf_get_lb_pblock(sb, loc, block)); | 95 | bh = udf_tread(sb, udf_get_lb_pblock(sb, &loc, block)); |
96 | if (!bh) | 96 | if (!bh) |
97 | retval = -EIO; | 97 | retval = -EIO; |
98 | 98 | ||
@@ -140,27 +140,29 @@ static inline int load_block_bitmap(struct super_block *sb, | |||
140 | return slot; | 140 | return slot; |
141 | } | 141 | } |
142 | 142 | ||
143 | static bool udf_add_free_space(struct udf_sb_info *sbi, | 143 | static void udf_add_free_space(struct super_block *sb, u16 partition, u32 cnt) |
144 | u16 partition, u32 cnt) | ||
145 | { | 144 | { |
145 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
146 | struct logicalVolIntegrityDesc *lvid; | 146 | struct logicalVolIntegrityDesc *lvid; |
147 | 147 | ||
148 | if (sbi->s_lvid_bh == NULL) | 148 | if (!sbi->s_lvid_bh) |
149 | return false; | 149 | return; |
150 | 150 | ||
151 | lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; | 151 | lvid = (struct logicalVolIntegrityDesc *)sbi->s_lvid_bh->b_data; |
152 | le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); | 152 | le32_add_cpu(&lvid->freeSpaceTable[partition], cnt); |
153 | return true; | 153 | udf_updated_lvid(sb); |
154 | } | 154 | } |
155 | 155 | ||
156 | static void udf_bitmap_free_blocks(struct super_block *sb, | 156 | static void udf_bitmap_free_blocks(struct super_block *sb, |
157 | struct inode *inode, | 157 | struct inode *inode, |
158 | struct udf_bitmap *bitmap, | 158 | struct udf_bitmap *bitmap, |
159 | kernel_lb_addr bloc, uint32_t offset, | 159 | struct kernel_lb_addr *bloc, |
160 | uint32_t offset, | ||
160 | uint32_t count) | 161 | uint32_t count) |
161 | { | 162 | { |
162 | struct udf_sb_info *sbi = UDF_SB(sb); | 163 | struct udf_sb_info *sbi = UDF_SB(sb); |
163 | struct buffer_head *bh = NULL; | 164 | struct buffer_head *bh = NULL; |
165 | struct udf_part_map *partmap; | ||
164 | unsigned long block; | 166 | unsigned long block; |
165 | unsigned long block_group; | 167 | unsigned long block_group; |
166 | unsigned long bit; | 168 | unsigned long bit; |
@@ -169,17 +171,17 @@ static void udf_bitmap_free_blocks(struct super_block *sb, | |||
169 | unsigned long overflow; | 171 | unsigned long overflow; |
170 | 172 | ||
171 | mutex_lock(&sbi->s_alloc_mutex); | 173 | mutex_lock(&sbi->s_alloc_mutex); |
172 | if (bloc.logicalBlockNum < 0 || | 174 | partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; |
173 | (bloc.logicalBlockNum + count) > | 175 | if (bloc->logicalBlockNum < 0 || |
174 | sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { | 176 | (bloc->logicalBlockNum + count) > |
177 | partmap->s_partition_len) { | ||
175 | udf_debug("%d < %d || %d + %d > %d\n", | 178 | udf_debug("%d < %d || %d + %d > %d\n", |
176 | bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, | 179 | bloc->logicalBlockNum, 0, bloc->logicalBlockNum, |
177 | sbi->s_partmaps[bloc.partitionReferenceNum]. | 180 | count, partmap->s_partition_len); |
178 | s_partition_len); | ||
179 | goto error_return; | 181 | goto error_return; |
180 | } | 182 | } |
181 | 183 | ||
182 | block = bloc.logicalBlockNum + offset + | 184 | block = bloc->logicalBlockNum + offset + |
183 | (sizeof(struct spaceBitmapDesc) << 3); | 185 | (sizeof(struct spaceBitmapDesc) << 3); |
184 | 186 | ||
185 | do { | 187 | do { |
@@ -207,7 +209,7 @@ static void udf_bitmap_free_blocks(struct super_block *sb, | |||
207 | } else { | 209 | } else { |
208 | if (inode) | 210 | if (inode) |
209 | vfs_dq_free_block(inode, 1); | 211 | vfs_dq_free_block(inode, 1); |
210 | udf_add_free_space(sbi, sbi->s_partition, 1); | 212 | udf_add_free_space(sb, sbi->s_partition, 1); |
211 | } | 213 | } |
212 | } | 214 | } |
213 | mark_buffer_dirty(bh); | 215 | mark_buffer_dirty(bh); |
@@ -218,9 +220,6 @@ static void udf_bitmap_free_blocks(struct super_block *sb, | |||
218 | } while (overflow); | 220 | } while (overflow); |
219 | 221 | ||
220 | error_return: | 222 | error_return: |
221 | sb->s_dirt = 1; | ||
222 | if (sbi->s_lvid_bh) | ||
223 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
224 | mutex_unlock(&sbi->s_alloc_mutex); | 223 | mutex_unlock(&sbi->s_alloc_mutex); |
225 | } | 224 | } |
226 | 225 | ||
@@ -277,9 +276,7 @@ static int udf_bitmap_prealloc_blocks(struct super_block *sb, | |||
277 | } while (block_count > 0); | 276 | } while (block_count > 0); |
278 | 277 | ||
279 | out: | 278 | out: |
280 | if (udf_add_free_space(sbi, partition, -alloc_count)) | 279 | udf_add_free_space(sb, partition, -alloc_count); |
281 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
282 | sb->s_dirt = 1; | ||
283 | mutex_unlock(&sbi->s_alloc_mutex); | 280 | mutex_unlock(&sbi->s_alloc_mutex); |
284 | return alloc_count; | 281 | return alloc_count; |
285 | } | 282 | } |
@@ -409,9 +406,7 @@ got_block: | |||
409 | 406 | ||
410 | mark_buffer_dirty(bh); | 407 | mark_buffer_dirty(bh); |
411 | 408 | ||
412 | if (udf_add_free_space(sbi, partition, -1)) | 409 | udf_add_free_space(sb, partition, -1); |
413 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
414 | sb->s_dirt = 1; | ||
415 | mutex_unlock(&sbi->s_alloc_mutex); | 410 | mutex_unlock(&sbi->s_alloc_mutex); |
416 | *err = 0; | 411 | *err = 0; |
417 | return newblock; | 412 | return newblock; |
@@ -425,26 +420,28 @@ error_return: | |||
425 | static void udf_table_free_blocks(struct super_block *sb, | 420 | static void udf_table_free_blocks(struct super_block *sb, |
426 | struct inode *inode, | 421 | struct inode *inode, |
427 | struct inode *table, | 422 | struct inode *table, |
428 | kernel_lb_addr bloc, uint32_t offset, | 423 | struct kernel_lb_addr *bloc, |
424 | uint32_t offset, | ||
429 | uint32_t count) | 425 | uint32_t count) |
430 | { | 426 | { |
431 | struct udf_sb_info *sbi = UDF_SB(sb); | 427 | struct udf_sb_info *sbi = UDF_SB(sb); |
428 | struct udf_part_map *partmap; | ||
432 | uint32_t start, end; | 429 | uint32_t start, end; |
433 | uint32_t elen; | 430 | uint32_t elen; |
434 | kernel_lb_addr eloc; | 431 | struct kernel_lb_addr eloc; |
435 | struct extent_position oepos, epos; | 432 | struct extent_position oepos, epos; |
436 | int8_t etype; | 433 | int8_t etype; |
437 | int i; | 434 | int i; |
438 | struct udf_inode_info *iinfo; | 435 | struct udf_inode_info *iinfo; |
439 | 436 | ||
440 | mutex_lock(&sbi->s_alloc_mutex); | 437 | mutex_lock(&sbi->s_alloc_mutex); |
441 | if (bloc.logicalBlockNum < 0 || | 438 | partmap = &sbi->s_partmaps[bloc->partitionReferenceNum]; |
442 | (bloc.logicalBlockNum + count) > | 439 | if (bloc->logicalBlockNum < 0 || |
443 | sbi->s_partmaps[bloc.partitionReferenceNum].s_partition_len) { | 440 | (bloc->logicalBlockNum + count) > |
441 | partmap->s_partition_len) { | ||
444 | udf_debug("%d < %d || %d + %d > %d\n", | 442 | udf_debug("%d < %d || %d + %d > %d\n", |
445 | bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, | 443 | bloc.logicalBlockNum, 0, bloc.logicalBlockNum, count, |
446 | sbi->s_partmaps[bloc.partitionReferenceNum]. | 444 | partmap->s_partition_len); |
447 | s_partition_len); | ||
448 | goto error_return; | 445 | goto error_return; |
449 | } | 446 | } |
450 | 447 | ||
@@ -453,11 +450,10 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
453 | could occure, but.. oh well */ | 450 | could occure, but.. oh well */ |
454 | if (inode) | 451 | if (inode) |
455 | vfs_dq_free_block(inode, count); | 452 | vfs_dq_free_block(inode, count); |
456 | if (udf_add_free_space(sbi, sbi->s_partition, count)) | 453 | udf_add_free_space(sb, sbi->s_partition, count); |
457 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
458 | 454 | ||
459 | start = bloc.logicalBlockNum + offset; | 455 | start = bloc->logicalBlockNum + offset; |
460 | end = bloc.logicalBlockNum + offset + count - 1; | 456 | end = bloc->logicalBlockNum + offset + count - 1; |
461 | 457 | ||
462 | epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry); | 458 | epos.offset = oepos.offset = sizeof(struct unallocSpaceEntry); |
463 | elen = 0; | 459 | elen = 0; |
@@ -483,7 +479,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
483 | start += count; | 479 | start += count; |
484 | count = 0; | 480 | count = 0; |
485 | } | 481 | } |
486 | udf_write_aext(table, &oepos, eloc, elen, 1); | 482 | udf_write_aext(table, &oepos, &eloc, elen, 1); |
487 | } else if (eloc.logicalBlockNum == (end + 1)) { | 483 | } else if (eloc.logicalBlockNum == (end + 1)) { |
488 | if ((0x3FFFFFFF - elen) < | 484 | if ((0x3FFFFFFF - elen) < |
489 | (count << sb->s_blocksize_bits)) { | 485 | (count << sb->s_blocksize_bits)) { |
@@ -502,7 +498,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
502 | end -= count; | 498 | end -= count; |
503 | count = 0; | 499 | count = 0; |
504 | } | 500 | } |
505 | udf_write_aext(table, &oepos, eloc, elen, 1); | 501 | udf_write_aext(table, &oepos, &eloc, elen, 1); |
506 | } | 502 | } |
507 | 503 | ||
508 | if (epos.bh != oepos.bh) { | 504 | if (epos.bh != oepos.bh) { |
@@ -532,8 +528,8 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
532 | */ | 528 | */ |
533 | 529 | ||
534 | int adsize; | 530 | int adsize; |
535 | short_ad *sad = NULL; | 531 | struct short_ad *sad = NULL; |
536 | long_ad *lad = NULL; | 532 | struct long_ad *lad = NULL; |
537 | struct allocExtDesc *aed; | 533 | struct allocExtDesc *aed; |
538 | 534 | ||
539 | eloc.logicalBlockNum = start; | 535 | eloc.logicalBlockNum = start; |
@@ -541,9 +537,9 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
541 | (count << sb->s_blocksize_bits); | 537 | (count << sb->s_blocksize_bits); |
542 | 538 | ||
543 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 539 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
544 | adsize = sizeof(short_ad); | 540 | adsize = sizeof(struct short_ad); |
545 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 541 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
546 | adsize = sizeof(long_ad); | 542 | adsize = sizeof(struct long_ad); |
547 | else { | 543 | else { |
548 | brelse(oepos.bh); | 544 | brelse(oepos.bh); |
549 | brelse(epos.bh); | 545 | brelse(epos.bh); |
@@ -563,7 +559,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
563 | elen -= sb->s_blocksize; | 559 | elen -= sb->s_blocksize; |
564 | 560 | ||
565 | epos.bh = udf_tread(sb, | 561 | epos.bh = udf_tread(sb, |
566 | udf_get_lb_pblock(sb, epos.block, 0)); | 562 | udf_get_lb_pblock(sb, &epos.block, 0)); |
567 | if (!epos.bh) { | 563 | if (!epos.bh) { |
568 | brelse(oepos.bh); | 564 | brelse(oepos.bh); |
569 | goto error_return; | 565 | goto error_return; |
@@ -601,15 +597,15 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
601 | if (sbi->s_udfrev >= 0x0200) | 597 | if (sbi->s_udfrev >= 0x0200) |
602 | udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, | 598 | udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, |
603 | 3, 1, epos.block.logicalBlockNum, | 599 | 3, 1, epos.block.logicalBlockNum, |
604 | sizeof(tag)); | 600 | sizeof(struct tag)); |
605 | else | 601 | else |
606 | udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, | 602 | udf_new_tag(epos.bh->b_data, TAG_IDENT_AED, |
607 | 2, 1, epos.block.logicalBlockNum, | 603 | 2, 1, epos.block.logicalBlockNum, |
608 | sizeof(tag)); | 604 | sizeof(struct tag)); |
609 | 605 | ||
610 | switch (iinfo->i_alloc_type) { | 606 | switch (iinfo->i_alloc_type) { |
611 | case ICBTAG_FLAG_AD_SHORT: | 607 | case ICBTAG_FLAG_AD_SHORT: |
612 | sad = (short_ad *)sptr; | 608 | sad = (struct short_ad *)sptr; |
613 | sad->extLength = cpu_to_le32( | 609 | sad->extLength = cpu_to_le32( |
614 | EXT_NEXT_EXTENT_ALLOCDECS | | 610 | EXT_NEXT_EXTENT_ALLOCDECS | |
615 | sb->s_blocksize); | 611 | sb->s_blocksize); |
@@ -617,7 +613,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
617 | cpu_to_le32(epos.block.logicalBlockNum); | 613 | cpu_to_le32(epos.block.logicalBlockNum); |
618 | break; | 614 | break; |
619 | case ICBTAG_FLAG_AD_LONG: | 615 | case ICBTAG_FLAG_AD_LONG: |
620 | lad = (long_ad *)sptr; | 616 | lad = (struct long_ad *)sptr; |
621 | lad->extLength = cpu_to_le32( | 617 | lad->extLength = cpu_to_le32( |
622 | EXT_NEXT_EXTENT_ALLOCDECS | | 618 | EXT_NEXT_EXTENT_ALLOCDECS | |
623 | sb->s_blocksize); | 619 | sb->s_blocksize); |
@@ -635,7 +631,7 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
635 | 631 | ||
636 | /* It's possible that stealing the block emptied the extent */ | 632 | /* It's possible that stealing the block emptied the extent */ |
637 | if (elen) { | 633 | if (elen) { |
638 | udf_write_aext(table, &epos, eloc, elen, 1); | 634 | udf_write_aext(table, &epos, &eloc, elen, 1); |
639 | 635 | ||
640 | if (!epos.bh) { | 636 | if (!epos.bh) { |
641 | iinfo->i_lenAlloc += adsize; | 637 | iinfo->i_lenAlloc += adsize; |
@@ -653,7 +649,6 @@ static void udf_table_free_blocks(struct super_block *sb, | |||
653 | brelse(oepos.bh); | 649 | brelse(oepos.bh); |
654 | 650 | ||
655 | error_return: | 651 | error_return: |
656 | sb->s_dirt = 1; | ||
657 | mutex_unlock(&sbi->s_alloc_mutex); | 652 | mutex_unlock(&sbi->s_alloc_mutex); |
658 | return; | 653 | return; |
659 | } | 654 | } |
@@ -666,7 +661,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, | |||
666 | struct udf_sb_info *sbi = UDF_SB(sb); | 661 | struct udf_sb_info *sbi = UDF_SB(sb); |
667 | int alloc_count = 0; | 662 | int alloc_count = 0; |
668 | uint32_t elen, adsize; | 663 | uint32_t elen, adsize; |
669 | kernel_lb_addr eloc; | 664 | struct kernel_lb_addr eloc; |
670 | struct extent_position epos; | 665 | struct extent_position epos; |
671 | int8_t etype = -1; | 666 | int8_t etype = -1; |
672 | struct udf_inode_info *iinfo; | 667 | struct udf_inode_info *iinfo; |
@@ -677,9 +672,9 @@ static int udf_table_prealloc_blocks(struct super_block *sb, | |||
677 | 672 | ||
678 | iinfo = UDF_I(table); | 673 | iinfo = UDF_I(table); |
679 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 674 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
680 | adsize = sizeof(short_ad); | 675 | adsize = sizeof(struct short_ad); |
681 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 676 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
682 | adsize = sizeof(long_ad); | 677 | adsize = sizeof(struct long_ad); |
683 | else | 678 | else |
684 | return 0; | 679 | return 0; |
685 | 680 | ||
@@ -707,7 +702,7 @@ static int udf_table_prealloc_blocks(struct super_block *sb, | |||
707 | alloc_count = block_count; | 702 | alloc_count = block_count; |
708 | eloc.logicalBlockNum += alloc_count; | 703 | eloc.logicalBlockNum += alloc_count; |
709 | elen -= (alloc_count << sb->s_blocksize_bits); | 704 | elen -= (alloc_count << sb->s_blocksize_bits); |
710 | udf_write_aext(table, &epos, eloc, | 705 | udf_write_aext(table, &epos, &eloc, |
711 | (etype << 30) | elen, 1); | 706 | (etype << 30) | elen, 1); |
712 | } else | 707 | } else |
713 | udf_delete_aext(table, epos, eloc, | 708 | udf_delete_aext(table, epos, eloc, |
@@ -718,10 +713,8 @@ static int udf_table_prealloc_blocks(struct super_block *sb, | |||
718 | 713 | ||
719 | brelse(epos.bh); | 714 | brelse(epos.bh); |
720 | 715 | ||
721 | if (alloc_count && udf_add_free_space(sbi, partition, -alloc_count)) { | 716 | if (alloc_count) |
722 | mark_buffer_dirty(sbi->s_lvid_bh); | 717 | udf_add_free_space(sb, partition, -alloc_count); |
723 | sb->s_dirt = 1; | ||
724 | } | ||
725 | mutex_unlock(&sbi->s_alloc_mutex); | 718 | mutex_unlock(&sbi->s_alloc_mutex); |
726 | return alloc_count; | 719 | return alloc_count; |
727 | } | 720 | } |
@@ -735,7 +728,7 @@ static int udf_table_new_block(struct super_block *sb, | |||
735 | uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; | 728 | uint32_t spread = 0xFFFFFFFF, nspread = 0xFFFFFFFF; |
736 | uint32_t newblock = 0, adsize; | 729 | uint32_t newblock = 0, adsize; |
737 | uint32_t elen, goal_elen = 0; | 730 | uint32_t elen, goal_elen = 0; |
738 | kernel_lb_addr eloc, uninitialized_var(goal_eloc); | 731 | struct kernel_lb_addr eloc, uninitialized_var(goal_eloc); |
739 | struct extent_position epos, goal_epos; | 732 | struct extent_position epos, goal_epos; |
740 | int8_t etype; | 733 | int8_t etype; |
741 | struct udf_inode_info *iinfo = UDF_I(table); | 734 | struct udf_inode_info *iinfo = UDF_I(table); |
@@ -743,9 +736,9 @@ static int udf_table_new_block(struct super_block *sb, | |||
743 | *err = -ENOSPC; | 736 | *err = -ENOSPC; |
744 | 737 | ||
745 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 738 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
746 | adsize = sizeof(short_ad); | 739 | adsize = sizeof(struct short_ad); |
747 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 740 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
748 | adsize = sizeof(long_ad); | 741 | adsize = sizeof(struct long_ad); |
749 | else | 742 | else |
750 | return newblock; | 743 | return newblock; |
751 | 744 | ||
@@ -814,46 +807,37 @@ static int udf_table_new_block(struct super_block *sb, | |||
814 | } | 807 | } |
815 | 808 | ||
816 | if (goal_elen) | 809 | if (goal_elen) |
817 | udf_write_aext(table, &goal_epos, goal_eloc, goal_elen, 1); | 810 | udf_write_aext(table, &goal_epos, &goal_eloc, goal_elen, 1); |
818 | else | 811 | else |
819 | udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); | 812 | udf_delete_aext(table, goal_epos, goal_eloc, goal_elen); |
820 | brelse(goal_epos.bh); | 813 | brelse(goal_epos.bh); |
821 | 814 | ||
822 | if (udf_add_free_space(sbi, partition, -1)) | 815 | udf_add_free_space(sb, partition, -1); |
823 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
824 | 816 | ||
825 | sb->s_dirt = 1; | ||
826 | mutex_unlock(&sbi->s_alloc_mutex); | 817 | mutex_unlock(&sbi->s_alloc_mutex); |
827 | *err = 0; | 818 | *err = 0; |
828 | return newblock; | 819 | return newblock; |
829 | } | 820 | } |
830 | 821 | ||
831 | inline void udf_free_blocks(struct super_block *sb, | 822 | void udf_free_blocks(struct super_block *sb, struct inode *inode, |
832 | struct inode *inode, | 823 | struct kernel_lb_addr *bloc, uint32_t offset, |
833 | kernel_lb_addr bloc, uint32_t offset, | 824 | uint32_t count) |
834 | uint32_t count) | ||
835 | { | 825 | { |
836 | uint16_t partition = bloc.partitionReferenceNum; | 826 | uint16_t partition = bloc->partitionReferenceNum; |
837 | struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; | 827 | struct udf_part_map *map = &UDF_SB(sb)->s_partmaps[partition]; |
838 | 828 | ||
839 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { | 829 | if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_BITMAP) { |
840 | return udf_bitmap_free_blocks(sb, inode, | 830 | udf_bitmap_free_blocks(sb, inode, map->s_uspace.s_bitmap, |
841 | map->s_uspace.s_bitmap, | 831 | bloc, offset, count); |
842 | bloc, offset, count); | ||
843 | } else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { | 832 | } else if (map->s_partition_flags & UDF_PART_FLAG_UNALLOC_TABLE) { |
844 | return udf_table_free_blocks(sb, inode, | 833 | udf_table_free_blocks(sb, inode, map->s_uspace.s_table, |
845 | map->s_uspace.s_table, | 834 | bloc, offset, count); |
846 | bloc, offset, count); | ||
847 | } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { | 835 | } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_BITMAP) { |
848 | return udf_bitmap_free_blocks(sb, inode, | 836 | udf_bitmap_free_blocks(sb, inode, map->s_fspace.s_bitmap, |
849 | map->s_fspace.s_bitmap, | 837 | bloc, offset, count); |
850 | bloc, offset, count); | ||
851 | } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { | 838 | } else if (map->s_partition_flags & UDF_PART_FLAG_FREED_TABLE) { |
852 | return udf_table_free_blocks(sb, inode, | 839 | udf_table_free_blocks(sb, inode, map->s_fspace.s_table, |
853 | map->s_fspace.s_table, | 840 | bloc, offset, count); |
854 | bloc, offset, count); | ||
855 | } else { | ||
856 | return; | ||
857 | } | 841 | } |
858 | } | 842 | } |
859 | 843 | ||
diff --git a/fs/udf/dir.c b/fs/udf/dir.c index 62dc270c69d1..2efd4d5291b6 100644 --- a/fs/udf/dir.c +++ b/fs/udf/dir.c | |||
@@ -51,7 +51,7 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
51 | uint8_t lfi; | 51 | uint8_t lfi; |
52 | loff_t size = udf_ext0_offset(dir) + dir->i_size; | 52 | loff_t size = udf_ext0_offset(dir) + dir->i_size; |
53 | struct buffer_head *tmp, *bha[16]; | 53 | struct buffer_head *tmp, *bha[16]; |
54 | kernel_lb_addr eloc; | 54 | struct kernel_lb_addr eloc; |
55 | uint32_t elen; | 55 | uint32_t elen; |
56 | sector_t offset; | 56 | sector_t offset; |
57 | int i, num, ret = 0; | 57 | int i, num, ret = 0; |
@@ -80,13 +80,13 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
80 | ret = -ENOENT; | 80 | ret = -ENOENT; |
81 | goto out; | 81 | goto out; |
82 | } | 82 | } |
83 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 83 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); |
84 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 84 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
85 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 85 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
86 | epos.offset -= sizeof(short_ad); | 86 | epos.offset -= sizeof(struct short_ad); |
87 | else if (iinfo->i_alloc_type == | 87 | else if (iinfo->i_alloc_type == |
88 | ICBTAG_FLAG_AD_LONG) | 88 | ICBTAG_FLAG_AD_LONG) |
89 | epos.offset -= sizeof(long_ad); | 89 | epos.offset -= sizeof(struct long_ad); |
90 | } else { | 90 | } else { |
91 | offset = 0; | 91 | offset = 0; |
92 | } | 92 | } |
@@ -101,7 +101,7 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
101 | if (i + offset > (elen >> dir->i_sb->s_blocksize_bits)) | 101 | if (i + offset > (elen >> dir->i_sb->s_blocksize_bits)) |
102 | i = (elen >> dir->i_sb->s_blocksize_bits) - offset; | 102 | i = (elen >> dir->i_sb->s_blocksize_bits) - offset; |
103 | for (num = 0; i > 0; i--) { | 103 | for (num = 0; i > 0; i--) { |
104 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset + i); | 104 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset + i); |
105 | tmp = udf_tgetblk(dir->i_sb, block); | 105 | tmp = udf_tgetblk(dir->i_sb, block); |
106 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) | 106 | if (tmp && !buffer_uptodate(tmp) && !buffer_locked(tmp)) |
107 | bha[num++] = tmp; | 107 | bha[num++] = tmp; |
@@ -161,9 +161,9 @@ static int do_udf_readdir(struct inode *dir, struct file *filp, | |||
161 | memcpy(fname, "..", flen); | 161 | memcpy(fname, "..", flen); |
162 | dt_type = DT_DIR; | 162 | dt_type = DT_DIR; |
163 | } else { | 163 | } else { |
164 | kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); | 164 | struct kernel_lb_addr tloc = lelb_to_cpu(cfi.icb.extLocation); |
165 | 165 | ||
166 | iblock = udf_get_lb_pblock(dir->i_sb, tloc, 0); | 166 | iblock = udf_get_lb_pblock(dir->i_sb, &tloc, 0); |
167 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); | 167 | flen = udf_get_filename(dir->i_sb, nameptr, fname, lfi); |
168 | dt_type = DT_UNKNOWN; | 168 | dt_type = DT_UNKNOWN; |
169 | } | 169 | } |
diff --git a/fs/udf/directory.c b/fs/udf/directory.c index 2820f8fcf4cc..1d2c570704c8 100644 --- a/fs/udf/directory.c +++ b/fs/udf/directory.c | |||
@@ -20,7 +20,7 @@ | |||
20 | 20 | ||
21 | #if 0 | 21 | #if 0 |
22 | static uint8_t *udf_filead_read(struct inode *dir, uint8_t *tmpad, | 22 | static uint8_t *udf_filead_read(struct inode *dir, uint8_t *tmpad, |
23 | uint8_t ad_size, kernel_lb_addr fe_loc, | 23 | uint8_t ad_size, struct kernel_lb_addr fe_loc, |
24 | int *pos, int *offset, struct buffer_head **bh, | 24 | int *pos, int *offset, struct buffer_head **bh, |
25 | int *error) | 25 | int *error) |
26 | { | 26 | { |
@@ -75,7 +75,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, | |||
75 | struct udf_fileident_bh *fibh, | 75 | struct udf_fileident_bh *fibh, |
76 | struct fileIdentDesc *cfi, | 76 | struct fileIdentDesc *cfi, |
77 | struct extent_position *epos, | 77 | struct extent_position *epos, |
78 | kernel_lb_addr *eloc, uint32_t *elen, | 78 | struct kernel_lb_addr *eloc, uint32_t *elen, |
79 | sector_t *offset) | 79 | sector_t *offset) |
80 | { | 80 | { |
81 | struct fileIdentDesc *fi; | 81 | struct fileIdentDesc *fi; |
@@ -111,7 +111,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, | |||
111 | (EXT_RECORDED_ALLOCATED >> 30)) | 111 | (EXT_RECORDED_ALLOCATED >> 30)) |
112 | return NULL; | 112 | return NULL; |
113 | 113 | ||
114 | block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); | 114 | block = udf_get_lb_pblock(dir->i_sb, eloc, *offset); |
115 | 115 | ||
116 | (*offset)++; | 116 | (*offset)++; |
117 | 117 | ||
@@ -131,7 +131,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, | |||
131 | if (i + *offset > (*elen >> blocksize_bits)) | 131 | if (i + *offset > (*elen >> blocksize_bits)) |
132 | i = (*elen >> blocksize_bits)-*offset; | 132 | i = (*elen >> blocksize_bits)-*offset; |
133 | for (num = 0; i > 0; i--) { | 133 | for (num = 0; i > 0; i--) { |
134 | block = udf_get_lb_pblock(dir->i_sb, *eloc, | 134 | block = udf_get_lb_pblock(dir->i_sb, eloc, |
135 | *offset + i); | 135 | *offset + i); |
136 | tmp = udf_tgetblk(dir->i_sb, block); | 136 | tmp = udf_tgetblk(dir->i_sb, block); |
137 | if (tmp && !buffer_uptodate(tmp) && | 137 | if (tmp && !buffer_uptodate(tmp) && |
@@ -169,7 +169,7 @@ struct fileIdentDesc *udf_fileident_read(struct inode *dir, loff_t *nf_pos, | |||
169 | (EXT_RECORDED_ALLOCATED >> 30)) | 169 | (EXT_RECORDED_ALLOCATED >> 30)) |
170 | return NULL; | 170 | return NULL; |
171 | 171 | ||
172 | block = udf_get_lb_pblock(dir->i_sb, *eloc, *offset); | 172 | block = udf_get_lb_pblock(dir->i_sb, eloc, *offset); |
173 | 173 | ||
174 | (*offset)++; | 174 | (*offset)++; |
175 | 175 | ||
@@ -249,9 +249,9 @@ struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, int *offset) | |||
249 | } | 249 | } |
250 | 250 | ||
251 | #if 0 | 251 | #if 0 |
252 | static extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) | 252 | static struct extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) |
253 | { | 253 | { |
254 | extent_ad *ext; | 254 | struct extent_ad *ext; |
255 | struct fileEntry *fe; | 255 | struct fileEntry *fe; |
256 | uint8_t *ptr; | 256 | uint8_t *ptr; |
257 | 257 | ||
@@ -274,54 +274,54 @@ static extent_ad *udf_get_fileextent(void *buffer, int bufsize, int *offset) | |||
274 | if ((*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs))) | 274 | if ((*offset > 0) && (*offset < le32_to_cpu(fe->lengthAllocDescs))) |
275 | ptr += *offset; | 275 | ptr += *offset; |
276 | 276 | ||
277 | ext = (extent_ad *)ptr; | 277 | ext = (struct extent_ad *)ptr; |
278 | 278 | ||
279 | *offset = *offset + sizeof(extent_ad); | 279 | *offset = *offset + sizeof(struct extent_ad); |
280 | return ext; | 280 | return ext; |
281 | } | 281 | } |
282 | #endif | 282 | #endif |
283 | 283 | ||
284 | short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset, | 284 | struct short_ad *udf_get_fileshortad(uint8_t *ptr, int maxoffset, uint32_t *offset, |
285 | int inc) | 285 | int inc) |
286 | { | 286 | { |
287 | short_ad *sa; | 287 | struct short_ad *sa; |
288 | 288 | ||
289 | if ((!ptr) || (!offset)) { | 289 | if ((!ptr) || (!offset)) { |
290 | printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); | 290 | printk(KERN_ERR "udf: udf_get_fileshortad() invalidparms\n"); |
291 | return NULL; | 291 | return NULL; |
292 | } | 292 | } |
293 | 293 | ||
294 | if ((*offset + sizeof(short_ad)) > maxoffset) | 294 | if ((*offset + sizeof(struct short_ad)) > maxoffset) |
295 | return NULL; | 295 | return NULL; |
296 | else { | 296 | else { |
297 | sa = (short_ad *)ptr; | 297 | sa = (struct short_ad *)ptr; |
298 | if (sa->extLength == 0) | 298 | if (sa->extLength == 0) |
299 | return NULL; | 299 | return NULL; |
300 | } | 300 | } |
301 | 301 | ||
302 | if (inc) | 302 | if (inc) |
303 | *offset += sizeof(short_ad); | 303 | *offset += sizeof(struct short_ad); |
304 | return sa; | 304 | return sa; |
305 | } | 305 | } |
306 | 306 | ||
307 | long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) | 307 | struct long_ad *udf_get_filelongad(uint8_t *ptr, int maxoffset, uint32_t *offset, int inc) |
308 | { | 308 | { |
309 | long_ad *la; | 309 | struct long_ad *la; |
310 | 310 | ||
311 | if ((!ptr) || (!offset)) { | 311 | if ((!ptr) || (!offset)) { |
312 | printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); | 312 | printk(KERN_ERR "udf: udf_get_filelongad() invalidparms\n"); |
313 | return NULL; | 313 | return NULL; |
314 | } | 314 | } |
315 | 315 | ||
316 | if ((*offset + sizeof(long_ad)) > maxoffset) | 316 | if ((*offset + sizeof(struct long_ad)) > maxoffset) |
317 | return NULL; | 317 | return NULL; |
318 | else { | 318 | else { |
319 | la = (long_ad *)ptr; | 319 | la = (struct long_ad *)ptr; |
320 | if (la->extLength == 0) | 320 | if (la->extLength == 0) |
321 | return NULL; | 321 | return NULL; |
322 | } | 322 | } |
323 | 323 | ||
324 | if (inc) | 324 | if (inc) |
325 | *offset += sizeof(long_ad); | 325 | *offset += sizeof(struct long_ad); |
326 | return la; | 326 | return la; |
327 | } | 327 | } |
diff --git a/fs/udf/ecma_167.h b/fs/udf/ecma_167.h index a0974df82b31..4792b771aa80 100644 --- a/fs/udf/ecma_167.h +++ b/fs/udf/ecma_167.h | |||
@@ -38,10 +38,10 @@ | |||
38 | #define _ECMA_167_H 1 | 38 | #define _ECMA_167_H 1 |
39 | 39 | ||
40 | /* Character set specification (ECMA 167r3 1/7.2.1) */ | 40 | /* Character set specification (ECMA 167r3 1/7.2.1) */ |
41 | typedef struct { | 41 | struct charspec { |
42 | uint8_t charSetType; | 42 | uint8_t charSetType; |
43 | uint8_t charSetInfo[63]; | 43 | uint8_t charSetInfo[63]; |
44 | } __attribute__ ((packed)) charspec; | 44 | } __attribute__ ((packed)); |
45 | 45 | ||
46 | /* Character Set Type (ECMA 167r3 1/7.2.1.1) */ | 46 | /* Character Set Type (ECMA 167r3 1/7.2.1.1) */ |
47 | #define CHARSPEC_TYPE_CS0 0x00 /* (1/7.2.2) */ | 47 | #define CHARSPEC_TYPE_CS0 0x00 /* (1/7.2.2) */ |
@@ -57,7 +57,7 @@ typedef struct { | |||
57 | typedef uint8_t dstring; | 57 | typedef uint8_t dstring; |
58 | 58 | ||
59 | /* Timestamp (ECMA 167r3 1/7.3) */ | 59 | /* Timestamp (ECMA 167r3 1/7.3) */ |
60 | typedef struct { | 60 | struct timestamp { |
61 | __le16 typeAndTimezone; | 61 | __le16 typeAndTimezone; |
62 | __le16 year; | 62 | __le16 year; |
63 | uint8_t month; | 63 | uint8_t month; |
@@ -68,7 +68,7 @@ typedef struct { | |||
68 | uint8_t centiseconds; | 68 | uint8_t centiseconds; |
69 | uint8_t hundredsOfMicroseconds; | 69 | uint8_t hundredsOfMicroseconds; |
70 | uint8_t microseconds; | 70 | uint8_t microseconds; |
71 | } __attribute__ ((packed)) timestamp; | 71 | } __attribute__ ((packed)); |
72 | 72 | ||
73 | /* Type and Time Zone (ECMA 167r3 1/7.3.1) */ | 73 | /* Type and Time Zone (ECMA 167r3 1/7.3.1) */ |
74 | #define TIMESTAMP_TYPE_MASK 0xF000 | 74 | #define TIMESTAMP_TYPE_MASK 0xF000 |
@@ -78,11 +78,11 @@ typedef struct { | |||
78 | #define TIMESTAMP_TIMEZONE_MASK 0x0FFF | 78 | #define TIMESTAMP_TIMEZONE_MASK 0x0FFF |
79 | 79 | ||
80 | /* Entity identifier (ECMA 167r3 1/7.4) */ | 80 | /* Entity identifier (ECMA 167r3 1/7.4) */ |
81 | typedef struct { | 81 | struct regid { |
82 | uint8_t flags; | 82 | uint8_t flags; |
83 | uint8_t ident[23]; | 83 | uint8_t ident[23]; |
84 | uint8_t identSuffix[8]; | 84 | uint8_t identSuffix[8]; |
85 | } __attribute__ ((packed)) regid; | 85 | } __attribute__ ((packed)); |
86 | 86 | ||
87 | /* Flags (ECMA 167r3 1/7.4.1) */ | 87 | /* Flags (ECMA 167r3 1/7.4.1) */ |
88 | #define ENTITYID_FLAGS_DIRTY 0x00 | 88 | #define ENTITYID_FLAGS_DIRTY 0x00 |
@@ -126,38 +126,38 @@ struct terminatingExtendedAreaDesc { | |||
126 | 126 | ||
127 | /* Boot Descriptor (ECMA 167r3 2/9.4) */ | 127 | /* Boot Descriptor (ECMA 167r3 2/9.4) */ |
128 | struct bootDesc { | 128 | struct bootDesc { |
129 | uint8_t structType; | 129 | uint8_t structType; |
130 | uint8_t stdIdent[VSD_STD_ID_LEN]; | 130 | uint8_t stdIdent[VSD_STD_ID_LEN]; |
131 | uint8_t structVersion; | 131 | uint8_t structVersion; |
132 | uint8_t reserved1; | 132 | uint8_t reserved1; |
133 | regid archType; | 133 | struct regid archType; |
134 | regid bootIdent; | 134 | struct regid bootIdent; |
135 | __le32 bootExtLocation; | 135 | __le32 bootExtLocation; |
136 | __le32 bootExtLength; | 136 | __le32 bootExtLength; |
137 | __le64 loadAddress; | 137 | __le64 loadAddress; |
138 | __le64 startAddress; | 138 | __le64 startAddress; |
139 | timestamp descCreationDateAndTime; | 139 | struct timestamp descCreationDateAndTime; |
140 | __le16 flags; | 140 | __le16 flags; |
141 | uint8_t reserved2[32]; | 141 | uint8_t reserved2[32]; |
142 | uint8_t bootUse[1906]; | 142 | uint8_t bootUse[1906]; |
143 | } __attribute__ ((packed)); | 143 | } __attribute__ ((packed)); |
144 | 144 | ||
145 | /* Flags (ECMA 167r3 2/9.4.12) */ | 145 | /* Flags (ECMA 167r3 2/9.4.12) */ |
146 | #define BOOT_FLAGS_ERASE 0x01 | 146 | #define BOOT_FLAGS_ERASE 0x01 |
147 | 147 | ||
148 | /* Extent Descriptor (ECMA 167r3 3/7.1) */ | 148 | /* Extent Descriptor (ECMA 167r3 3/7.1) */ |
149 | typedef struct { | 149 | struct extent_ad { |
150 | __le32 extLength; | 150 | __le32 extLength; |
151 | __le32 extLocation; | 151 | __le32 extLocation; |
152 | } __attribute__ ((packed)) extent_ad; | 152 | } __attribute__ ((packed)); |
153 | 153 | ||
154 | typedef struct { | 154 | struct kernel_extent_ad { |
155 | uint32_t extLength; | 155 | uint32_t extLength; |
156 | uint32_t extLocation; | 156 | uint32_t extLocation; |
157 | } kernel_extent_ad; | 157 | }; |
158 | 158 | ||
159 | /* Descriptor Tag (ECMA 167r3 3/7.2) */ | 159 | /* Descriptor Tag (ECMA 167r3 3/7.2) */ |
160 | typedef struct { | 160 | struct tag { |
161 | __le16 tagIdent; | 161 | __le16 tagIdent; |
162 | __le16 descVersion; | 162 | __le16 descVersion; |
163 | uint8_t tagChecksum; | 163 | uint8_t tagChecksum; |
@@ -166,7 +166,7 @@ typedef struct { | |||
166 | __le16 descCRC; | 166 | __le16 descCRC; |
167 | __le16 descCRCLength; | 167 | __le16 descCRCLength; |
168 | __le32 tagLocation; | 168 | __le32 tagLocation; |
169 | } __attribute__ ((packed)) tag; | 169 | } __attribute__ ((packed)); |
170 | 170 | ||
171 | /* Tag Identifier (ECMA 167r3 3/7.2.1) */ | 171 | /* Tag Identifier (ECMA 167r3 3/7.2.1) */ |
172 | #define TAG_IDENT_PVD 0x0001 | 172 | #define TAG_IDENT_PVD 0x0001 |
@@ -190,28 +190,28 @@ struct NSRDesc { | |||
190 | 190 | ||
191 | /* Primary Volume Descriptor (ECMA 167r3 3/10.1) */ | 191 | /* Primary Volume Descriptor (ECMA 167r3 3/10.1) */ |
192 | struct primaryVolDesc { | 192 | struct primaryVolDesc { |
193 | tag descTag; | 193 | struct tag descTag; |
194 | __le32 volDescSeqNum; | 194 | __le32 volDescSeqNum; |
195 | __le32 primaryVolDescNum; | 195 | __le32 primaryVolDescNum; |
196 | dstring volIdent[32]; | 196 | dstring volIdent[32]; |
197 | __le16 volSeqNum; | 197 | __le16 volSeqNum; |
198 | __le16 maxVolSeqNum; | 198 | __le16 maxVolSeqNum; |
199 | __le16 interchangeLvl; | 199 | __le16 interchangeLvl; |
200 | __le16 maxInterchangeLvl; | 200 | __le16 maxInterchangeLvl; |
201 | __le32 charSetList; | 201 | __le32 charSetList; |
202 | __le32 maxCharSetList; | 202 | __le32 maxCharSetList; |
203 | dstring volSetIdent[128]; | 203 | dstring volSetIdent[128]; |
204 | charspec descCharSet; | 204 | struct charspec descCharSet; |
205 | charspec explanatoryCharSet; | 205 | struct charspec explanatoryCharSet; |
206 | extent_ad volAbstract; | 206 | struct extent_ad volAbstract; |
207 | extent_ad volCopyright; | 207 | struct extent_ad volCopyright; |
208 | regid appIdent; | 208 | struct regid appIdent; |
209 | timestamp recordingDateAndTime; | 209 | struct timestamp recordingDateAndTime; |
210 | regid impIdent; | 210 | struct regid impIdent; |
211 | uint8_t impUse[64]; | 211 | uint8_t impUse[64]; |
212 | __le32 predecessorVolDescSeqLocation; | 212 | __le32 predecessorVolDescSeqLocation; |
213 | __le16 flags; | 213 | __le16 flags; |
214 | uint8_t reserved[22]; | 214 | uint8_t reserved[22]; |
215 | } __attribute__ ((packed)); | 215 | } __attribute__ ((packed)); |
216 | 216 | ||
217 | /* Flags (ECMA 167r3 3/10.1.21) */ | 217 | /* Flags (ECMA 167r3 3/10.1.21) */ |
@@ -219,40 +219,40 @@ struct primaryVolDesc { | |||
219 | 219 | ||
220 | /* Anchor Volume Descriptor Pointer (ECMA 167r3 3/10.2) */ | 220 | /* Anchor Volume Descriptor Pointer (ECMA 167r3 3/10.2) */ |
221 | struct anchorVolDescPtr { | 221 | struct anchorVolDescPtr { |
222 | tag descTag; | 222 | struct tag descTag; |
223 | extent_ad mainVolDescSeqExt; | 223 | struct extent_ad mainVolDescSeqExt; |
224 | extent_ad reserveVolDescSeqExt; | 224 | struct extent_ad reserveVolDescSeqExt; |
225 | uint8_t reserved[480]; | 225 | uint8_t reserved[480]; |
226 | } __attribute__ ((packed)); | 226 | } __attribute__ ((packed)); |
227 | 227 | ||
228 | /* Volume Descriptor Pointer (ECMA 167r3 3/10.3) */ | 228 | /* Volume Descriptor Pointer (ECMA 167r3 3/10.3) */ |
229 | struct volDescPtr { | 229 | struct volDescPtr { |
230 | tag descTag; | 230 | struct tag descTag; |
231 | __le32 volDescSeqNum; | 231 | __le32 volDescSeqNum; |
232 | extent_ad nextVolDescSeqExt; | 232 | struct extent_ad nextVolDescSeqExt; |
233 | uint8_t reserved[484]; | 233 | uint8_t reserved[484]; |
234 | } __attribute__ ((packed)); | 234 | } __attribute__ ((packed)); |
235 | 235 | ||
236 | /* Implementation Use Volume Descriptor (ECMA 167r3 3/10.4) */ | 236 | /* Implementation Use Volume Descriptor (ECMA 167r3 3/10.4) */ |
237 | struct impUseVolDesc { | 237 | struct impUseVolDesc { |
238 | tag descTag; | 238 | struct tag descTag; |
239 | __le32 volDescSeqNum; | 239 | __le32 volDescSeqNum; |
240 | regid impIdent; | 240 | struct regid impIdent; |
241 | uint8_t impUse[460]; | 241 | uint8_t impUse[460]; |
242 | } __attribute__ ((packed)); | 242 | } __attribute__ ((packed)); |
243 | 243 | ||
244 | /* Partition Descriptor (ECMA 167r3 3/10.5) */ | 244 | /* Partition Descriptor (ECMA 167r3 3/10.5) */ |
245 | struct partitionDesc { | 245 | struct partitionDesc { |
246 | tag descTag; | 246 | struct tag descTag; |
247 | __le32 volDescSeqNum; | 247 | __le32 volDescSeqNum; |
248 | __le16 partitionFlags; | 248 | __le16 partitionFlags; |
249 | __le16 partitionNumber; | 249 | __le16 partitionNumber; |
250 | regid partitionContents; | 250 | struct regid partitionContents; |
251 | uint8_t partitionContentsUse[128]; | 251 | uint8_t partitionContentsUse[128]; |
252 | __le32 accessType; | 252 | __le32 accessType; |
253 | __le32 partitionStartingLocation; | 253 | __le32 partitionStartingLocation; |
254 | __le32 partitionLength; | 254 | __le32 partitionLength; |
255 | regid impIdent; | 255 | struct regid impIdent; |
256 | uint8_t impUse[128]; | 256 | uint8_t impUse[128]; |
257 | uint8_t reserved[156]; | 257 | uint8_t reserved[156]; |
258 | } __attribute__ ((packed)); | 258 | } __attribute__ ((packed)); |
@@ -278,19 +278,19 @@ struct partitionDesc { | |||
278 | 278 | ||
279 | /* Logical Volume Descriptor (ECMA 167r3 3/10.6) */ | 279 | /* Logical Volume Descriptor (ECMA 167r3 3/10.6) */ |
280 | struct logicalVolDesc { | 280 | struct logicalVolDesc { |
281 | tag descTag; | 281 | struct tag descTag; |
282 | __le32 volDescSeqNum; | 282 | __le32 volDescSeqNum; |
283 | charspec descCharSet; | 283 | struct charspec descCharSet; |
284 | dstring logicalVolIdent[128]; | 284 | dstring logicalVolIdent[128]; |
285 | __le32 logicalBlockSize; | 285 | __le32 logicalBlockSize; |
286 | regid domainIdent; | 286 | struct regid domainIdent; |
287 | uint8_t logicalVolContentsUse[16]; | 287 | uint8_t logicalVolContentsUse[16]; |
288 | __le32 mapTableLength; | 288 | __le32 mapTableLength; |
289 | __le32 numPartitionMaps; | 289 | __le32 numPartitionMaps; |
290 | regid impIdent; | 290 | struct regid impIdent; |
291 | uint8_t impUse[128]; | 291 | uint8_t impUse[128]; |
292 | extent_ad integritySeqExt; | 292 | struct extent_ad integritySeqExt; |
293 | uint8_t partitionMaps[0]; | 293 | uint8_t partitionMaps[0]; |
294 | } __attribute__ ((packed)); | 294 | } __attribute__ ((packed)); |
295 | 295 | ||
296 | /* Generic Partition Map (ECMA 167r3 3/10.7.1) */ | 296 | /* Generic Partition Map (ECMA 167r3 3/10.7.1) */ |
@@ -322,30 +322,30 @@ struct genericPartitionMap2 { | |||
322 | 322 | ||
323 | /* Unallocated Space Descriptor (ECMA 167r3 3/10.8) */ | 323 | /* Unallocated Space Descriptor (ECMA 167r3 3/10.8) */ |
324 | struct unallocSpaceDesc { | 324 | struct unallocSpaceDesc { |
325 | tag descTag; | 325 | struct tag descTag; |
326 | __le32 volDescSeqNum; | 326 | __le32 volDescSeqNum; |
327 | __le32 numAllocDescs; | 327 | __le32 numAllocDescs; |
328 | extent_ad allocDescs[0]; | 328 | struct extent_ad allocDescs[0]; |
329 | } __attribute__ ((packed)); | 329 | } __attribute__ ((packed)); |
330 | 330 | ||
331 | /* Terminating Descriptor (ECMA 167r3 3/10.9) */ | 331 | /* Terminating Descriptor (ECMA 167r3 3/10.9) */ |
332 | struct terminatingDesc { | 332 | struct terminatingDesc { |
333 | tag descTag; | 333 | struct tag descTag; |
334 | uint8_t reserved[496]; | 334 | uint8_t reserved[496]; |
335 | } __attribute__ ((packed)); | 335 | } __attribute__ ((packed)); |
336 | 336 | ||
337 | /* Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */ | 337 | /* Logical Volume Integrity Descriptor (ECMA 167r3 3/10.10) */ |
338 | struct logicalVolIntegrityDesc { | 338 | struct logicalVolIntegrityDesc { |
339 | tag descTag; | 339 | struct tag descTag; |
340 | timestamp recordingDateAndTime; | 340 | struct timestamp recordingDateAndTime; |
341 | __le32 integrityType; | 341 | __le32 integrityType; |
342 | extent_ad nextIntegrityExt; | 342 | struct extent_ad nextIntegrityExt; |
343 | uint8_t logicalVolContentsUse[32]; | 343 | uint8_t logicalVolContentsUse[32]; |
344 | __le32 numOfPartitions; | 344 | __le32 numOfPartitions; |
345 | __le32 lengthOfImpUse; | 345 | __le32 lengthOfImpUse; |
346 | __le32 freeSpaceTable[0]; | 346 | __le32 freeSpaceTable[0]; |
347 | __le32 sizeTable[0]; | 347 | __le32 sizeTable[0]; |
348 | uint8_t impUse[0]; | 348 | uint8_t impUse[0]; |
349 | } __attribute__ ((packed)); | 349 | } __attribute__ ((packed)); |
350 | 350 | ||
351 | /* Integrity Type (ECMA 167r3 3/10.10.3) */ | 351 | /* Integrity Type (ECMA 167r3 3/10.10.3) */ |
@@ -353,50 +353,50 @@ struct logicalVolIntegrityDesc { | |||
353 | #define LVID_INTEGRITY_TYPE_CLOSE 0x00000001 | 353 | #define LVID_INTEGRITY_TYPE_CLOSE 0x00000001 |
354 | 354 | ||
355 | /* Recorded Address (ECMA 167r3 4/7.1) */ | 355 | /* Recorded Address (ECMA 167r3 4/7.1) */ |
356 | typedef struct { | 356 | struct lb_addr { |
357 | __le32 logicalBlockNum; | 357 | __le32 logicalBlockNum; |
358 | __le16 partitionReferenceNum; | 358 | __le16 partitionReferenceNum; |
359 | } __attribute__ ((packed)) lb_addr; | 359 | } __attribute__ ((packed)); |
360 | 360 | ||
361 | /* ... and its in-core analog */ | 361 | /* ... and its in-core analog */ |
362 | typedef struct { | 362 | struct kernel_lb_addr { |
363 | uint32_t logicalBlockNum; | 363 | uint32_t logicalBlockNum; |
364 | uint16_t partitionReferenceNum; | 364 | uint16_t partitionReferenceNum; |
365 | } kernel_lb_addr; | 365 | }; |
366 | 366 | ||
367 | /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ | 367 | /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ |
368 | typedef struct { | 368 | struct short_ad { |
369 | __le32 extLength; | 369 | __le32 extLength; |
370 | __le32 extPosition; | 370 | __le32 extPosition; |
371 | } __attribute__ ((packed)) short_ad; | 371 | } __attribute__ ((packed)); |
372 | 372 | ||
373 | /* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ | 373 | /* Long Allocation Descriptor (ECMA 167r3 4/14.14.2) */ |
374 | typedef struct { | 374 | struct long_ad { |
375 | __le32 extLength; | 375 | __le32 extLength; |
376 | lb_addr extLocation; | 376 | struct lb_addr extLocation; |
377 | uint8_t impUse[6]; | 377 | uint8_t impUse[6]; |
378 | } __attribute__ ((packed)) long_ad; | 378 | } __attribute__ ((packed)); |
379 | 379 | ||
380 | typedef struct { | 380 | struct kernel_long_ad { |
381 | uint32_t extLength; | 381 | uint32_t extLength; |
382 | kernel_lb_addr extLocation; | 382 | struct kernel_lb_addr extLocation; |
383 | uint8_t impUse[6]; | 383 | uint8_t impUse[6]; |
384 | } kernel_long_ad; | 384 | }; |
385 | 385 | ||
386 | /* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ | 386 | /* Extended Allocation Descriptor (ECMA 167r3 4/14.14.3) */ |
387 | typedef struct { | 387 | struct ext_ad { |
388 | __le32 extLength; | 388 | __le32 extLength; |
389 | __le32 recordedLength; | 389 | __le32 recordedLength; |
390 | __le32 informationLength; | 390 | __le32 informationLength; |
391 | lb_addr extLocation; | 391 | struct lb_addr extLocation; |
392 | } __attribute__ ((packed)) ext_ad; | 392 | } __attribute__ ((packed)); |
393 | 393 | ||
394 | typedef struct { | 394 | struct kernel_ext_ad { |
395 | uint32_t extLength; | 395 | uint32_t extLength; |
396 | uint32_t recordedLength; | 396 | uint32_t recordedLength; |
397 | uint32_t informationLength; | 397 | uint32_t informationLength; |
398 | kernel_lb_addr extLocation; | 398 | struct kernel_lb_addr extLocation; |
399 | } kernel_ext_ad; | 399 | }; |
400 | 400 | ||
401 | /* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */ | 401 | /* Descriptor Tag (ECMA 167r3 4/7.2 - See 3/7.2) */ |
402 | 402 | ||
@@ -415,44 +415,44 @@ typedef struct { | |||
415 | 415 | ||
416 | /* File Set Descriptor (ECMA 167r3 4/14.1) */ | 416 | /* File Set Descriptor (ECMA 167r3 4/14.1) */ |
417 | struct fileSetDesc { | 417 | struct fileSetDesc { |
418 | tag descTag; | 418 | struct tag descTag; |
419 | timestamp recordingDateAndTime; | 419 | struct timestamp recordingDateAndTime; |
420 | __le16 interchangeLvl; | 420 | __le16 interchangeLvl; |
421 | __le16 maxInterchangeLvl; | 421 | __le16 maxInterchangeLvl; |
422 | __le32 charSetList; | 422 | __le32 charSetList; |
423 | __le32 maxCharSetList; | 423 | __le32 maxCharSetList; |
424 | __le32 fileSetNum; | 424 | __le32 fileSetNum; |
425 | __le32 fileSetDescNum; | 425 | __le32 fileSetDescNum; |
426 | charspec logicalVolIdentCharSet; | 426 | struct charspec logicalVolIdentCharSet; |
427 | dstring logicalVolIdent[128]; | 427 | dstring logicalVolIdent[128]; |
428 | charspec fileSetCharSet; | 428 | struct charspec fileSetCharSet; |
429 | dstring fileSetIdent[32]; | 429 | dstring fileSetIdent[32]; |
430 | dstring copyrightFileIdent[32]; | 430 | dstring copyrightFileIdent[32]; |
431 | dstring abstractFileIdent[32]; | 431 | dstring abstractFileIdent[32]; |
432 | long_ad rootDirectoryICB; | 432 | struct long_ad rootDirectoryICB; |
433 | regid domainIdent; | 433 | struct regid domainIdent; |
434 | long_ad nextExt; | 434 | struct long_ad nextExt; |
435 | long_ad streamDirectoryICB; | 435 | struct long_ad streamDirectoryICB; |
436 | uint8_t reserved[32]; | 436 | uint8_t reserved[32]; |
437 | } __attribute__ ((packed)); | 437 | } __attribute__ ((packed)); |
438 | 438 | ||
439 | /* Partition Header Descriptor (ECMA 167r3 4/14.3) */ | 439 | /* Partition Header Descriptor (ECMA 167r3 4/14.3) */ |
440 | struct partitionHeaderDesc { | 440 | struct partitionHeaderDesc { |
441 | short_ad unallocSpaceTable; | 441 | struct short_ad unallocSpaceTable; |
442 | short_ad unallocSpaceBitmap; | 442 | struct short_ad unallocSpaceBitmap; |
443 | short_ad partitionIntegrityTable; | 443 | struct short_ad partitionIntegrityTable; |
444 | short_ad freedSpaceTable; | 444 | struct short_ad freedSpaceTable; |
445 | short_ad freedSpaceBitmap; | 445 | struct short_ad freedSpaceBitmap; |
446 | uint8_t reserved[88]; | 446 | uint8_t reserved[88]; |
447 | } __attribute__ ((packed)); | 447 | } __attribute__ ((packed)); |
448 | 448 | ||
449 | /* File Identifier Descriptor (ECMA 167r3 4/14.4) */ | 449 | /* File Identifier Descriptor (ECMA 167r3 4/14.4) */ |
450 | struct fileIdentDesc { | 450 | struct fileIdentDesc { |
451 | tag descTag; | 451 | struct tag descTag; |
452 | __le16 fileVersionNum; | 452 | __le16 fileVersionNum; |
453 | uint8_t fileCharacteristics; | 453 | uint8_t fileCharacteristics; |
454 | uint8_t lengthFileIdent; | 454 | uint8_t lengthFileIdent; |
455 | long_ad icb; | 455 | struct long_ad icb; |
456 | __le16 lengthOfImpUse; | 456 | __le16 lengthOfImpUse; |
457 | uint8_t impUse[0]; | 457 | uint8_t impUse[0]; |
458 | uint8_t fileIdent[0]; | 458 | uint8_t fileIdent[0]; |
@@ -468,22 +468,22 @@ struct fileIdentDesc { | |||
468 | 468 | ||
469 | /* Allocation Ext Descriptor (ECMA 167r3 4/14.5) */ | 469 | /* Allocation Ext Descriptor (ECMA 167r3 4/14.5) */ |
470 | struct allocExtDesc { | 470 | struct allocExtDesc { |
471 | tag descTag; | 471 | struct tag descTag; |
472 | __le32 previousAllocExtLocation; | 472 | __le32 previousAllocExtLocation; |
473 | __le32 lengthAllocDescs; | 473 | __le32 lengthAllocDescs; |
474 | } __attribute__ ((packed)); | 474 | } __attribute__ ((packed)); |
475 | 475 | ||
476 | /* ICB Tag (ECMA 167r3 4/14.6) */ | 476 | /* ICB Tag (ECMA 167r3 4/14.6) */ |
477 | typedef struct { | 477 | struct icbtag { |
478 | __le32 priorRecordedNumDirectEntries; | 478 | __le32 priorRecordedNumDirectEntries; |
479 | __le16 strategyType; | 479 | __le16 strategyType; |
480 | __le16 strategyParameter; | 480 | __le16 strategyParameter; |
481 | __le16 numEntries; | 481 | __le16 numEntries; |
482 | uint8_t reserved; | 482 | uint8_t reserved; |
483 | uint8_t fileType; | 483 | uint8_t fileType; |
484 | lb_addr parentICBLocation; | 484 | struct lb_addr parentICBLocation; |
485 | __le16 flags; | 485 | __le16 flags; |
486 | } __attribute__ ((packed)) icbtag; | 486 | } __attribute__ ((packed)); |
487 | 487 | ||
488 | /* Strategy Type (ECMA 167r3 4/14.6.2) */ | 488 | /* Strategy Type (ECMA 167r3 4/14.6.2) */ |
489 | #define ICBTAG_STRATEGY_TYPE_UNDEF 0x0000 | 489 | #define ICBTAG_STRATEGY_TYPE_UNDEF 0x0000 |
@@ -528,41 +528,41 @@ typedef struct { | |||
528 | 528 | ||
529 | /* Indirect Entry (ECMA 167r3 4/14.7) */ | 529 | /* Indirect Entry (ECMA 167r3 4/14.7) */ |
530 | struct indirectEntry { | 530 | struct indirectEntry { |
531 | tag descTag; | 531 | struct tag descTag; |
532 | icbtag icbTag; | 532 | struct icbtag icbTag; |
533 | long_ad indirectICB; | 533 | struct long_ad indirectICB; |
534 | } __attribute__ ((packed)); | 534 | } __attribute__ ((packed)); |
535 | 535 | ||
536 | /* Terminal Entry (ECMA 167r3 4/14.8) */ | 536 | /* Terminal Entry (ECMA 167r3 4/14.8) */ |
537 | struct terminalEntry { | 537 | struct terminalEntry { |
538 | tag descTag; | 538 | struct tag descTag; |
539 | icbtag icbTag; | 539 | struct icbtag icbTag; |
540 | } __attribute__ ((packed)); | 540 | } __attribute__ ((packed)); |
541 | 541 | ||
542 | /* File Entry (ECMA 167r3 4/14.9) */ | 542 | /* File Entry (ECMA 167r3 4/14.9) */ |
543 | struct fileEntry { | 543 | struct fileEntry { |
544 | tag descTag; | 544 | struct tag descTag; |
545 | icbtag icbTag; | 545 | struct icbtag icbTag; |
546 | __le32 uid; | 546 | __le32 uid; |
547 | __le32 gid; | 547 | __le32 gid; |
548 | __le32 permissions; | 548 | __le32 permissions; |
549 | __le16 fileLinkCount; | 549 | __le16 fileLinkCount; |
550 | uint8_t recordFormat; | 550 | uint8_t recordFormat; |
551 | uint8_t recordDisplayAttr; | 551 | uint8_t recordDisplayAttr; |
552 | __le32 recordLength; | 552 | __le32 recordLength; |
553 | __le64 informationLength; | 553 | __le64 informationLength; |
554 | __le64 logicalBlocksRecorded; | 554 | __le64 logicalBlocksRecorded; |
555 | timestamp accessTime; | 555 | struct timestamp accessTime; |
556 | timestamp modificationTime; | 556 | struct timestamp modificationTime; |
557 | timestamp attrTime; | 557 | struct timestamp attrTime; |
558 | __le32 checkpoint; | 558 | __le32 checkpoint; |
559 | long_ad extendedAttrICB; | 559 | struct long_ad extendedAttrICB; |
560 | regid impIdent; | 560 | struct regid impIdent; |
561 | __le64 uniqueID; | 561 | __le64 uniqueID; |
562 | __le32 lengthExtendedAttr; | 562 | __le32 lengthExtendedAttr; |
563 | __le32 lengthAllocDescs; | 563 | __le32 lengthAllocDescs; |
564 | uint8_t extendedAttr[0]; | 564 | uint8_t extendedAttr[0]; |
565 | uint8_t allocDescs[0]; | 565 | uint8_t allocDescs[0]; |
566 | } __attribute__ ((packed)); | 566 | } __attribute__ ((packed)); |
567 | 567 | ||
568 | /* Permissions (ECMA 167r3 4/14.9.5) */ | 568 | /* Permissions (ECMA 167r3 4/14.9.5) */ |
@@ -604,7 +604,7 @@ struct fileEntry { | |||
604 | 604 | ||
605 | /* Extended Attribute Header Descriptor (ECMA 167r3 4/14.10.1) */ | 605 | /* Extended Attribute Header Descriptor (ECMA 167r3 4/14.10.1) */ |
606 | struct extendedAttrHeaderDesc { | 606 | struct extendedAttrHeaderDesc { |
607 | tag descTag; | 607 | struct tag descTag; |
608 | __le32 impAttrLocation; | 608 | __le32 impAttrLocation; |
609 | __le32 appAttrLocation; | 609 | __le32 appAttrLocation; |
610 | } __attribute__ ((packed)); | 610 | } __attribute__ ((packed)); |
@@ -687,7 +687,7 @@ struct impUseExtAttr { | |||
687 | uint8_t reserved[3]; | 687 | uint8_t reserved[3]; |
688 | __le32 attrLength; | 688 | __le32 attrLength; |
689 | __le32 impUseLength; | 689 | __le32 impUseLength; |
690 | regid impIdent; | 690 | struct regid impIdent; |
691 | uint8_t impUse[0]; | 691 | uint8_t impUse[0]; |
692 | } __attribute__ ((packed)); | 692 | } __attribute__ ((packed)); |
693 | 693 | ||
@@ -698,7 +698,7 @@ struct appUseExtAttr { | |||
698 | uint8_t reserved[3]; | 698 | uint8_t reserved[3]; |
699 | __le32 attrLength; | 699 | __le32 attrLength; |
700 | __le32 appUseLength; | 700 | __le32 appUseLength; |
701 | regid appIdent; | 701 | struct regid appIdent; |
702 | uint8_t appUse[0]; | 702 | uint8_t appUse[0]; |
703 | } __attribute__ ((packed)); | 703 | } __attribute__ ((packed)); |
704 | 704 | ||
@@ -712,15 +712,15 @@ struct appUseExtAttr { | |||
712 | 712 | ||
713 | /* Unallocated Space Entry (ECMA 167r3 4/14.11) */ | 713 | /* Unallocated Space Entry (ECMA 167r3 4/14.11) */ |
714 | struct unallocSpaceEntry { | 714 | struct unallocSpaceEntry { |
715 | tag descTag; | 715 | struct tag descTag; |
716 | icbtag icbTag; | 716 | struct icbtag icbTag; |
717 | __le32 lengthAllocDescs; | 717 | __le32 lengthAllocDescs; |
718 | uint8_t allocDescs[0]; | 718 | uint8_t allocDescs[0]; |
719 | } __attribute__ ((packed)); | 719 | } __attribute__ ((packed)); |
720 | 720 | ||
721 | /* Space Bitmap Descriptor (ECMA 167r3 4/14.12) */ | 721 | /* Space Bitmap Descriptor (ECMA 167r3 4/14.12) */ |
722 | struct spaceBitmapDesc { | 722 | struct spaceBitmapDesc { |
723 | tag descTag; | 723 | struct tag descTag; |
724 | __le32 numOfBits; | 724 | __le32 numOfBits; |
725 | __le32 numOfBytes; | 725 | __le32 numOfBytes; |
726 | uint8_t bitmap[0]; | 726 | uint8_t bitmap[0]; |
@@ -728,13 +728,13 @@ struct spaceBitmapDesc { | |||
728 | 728 | ||
729 | /* Partition Integrity Entry (ECMA 167r3 4/14.13) */ | 729 | /* Partition Integrity Entry (ECMA 167r3 4/14.13) */ |
730 | struct partitionIntegrityEntry { | 730 | struct partitionIntegrityEntry { |
731 | tag descTag; | 731 | struct tag descTag; |
732 | icbtag icbTag; | 732 | struct icbtag icbTag; |
733 | timestamp recordingDateAndTime; | 733 | struct timestamp recordingDateAndTime; |
734 | uint8_t integrityType; | 734 | uint8_t integrityType; |
735 | uint8_t reserved[175]; | 735 | uint8_t reserved[175]; |
736 | regid impIdent; | 736 | struct regid impIdent; |
737 | uint8_t impUse[256]; | 737 | uint8_t impUse[256]; |
738 | } __attribute__ ((packed)); | 738 | } __attribute__ ((packed)); |
739 | 739 | ||
740 | /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ | 740 | /* Short Allocation Descriptor (ECMA 167r3 4/14.14.1) */ |
@@ -765,32 +765,32 @@ struct pathComponent { | |||
765 | 765 | ||
766 | /* File Entry (ECMA 167r3 4/14.17) */ | 766 | /* File Entry (ECMA 167r3 4/14.17) */ |
767 | struct extendedFileEntry { | 767 | struct extendedFileEntry { |
768 | tag descTag; | 768 | struct tag descTag; |
769 | icbtag icbTag; | 769 | struct icbtag icbTag; |
770 | __le32 uid; | 770 | __le32 uid; |
771 | __le32 gid; | 771 | __le32 gid; |
772 | __le32 permissions; | 772 | __le32 permissions; |
773 | __le16 fileLinkCount; | 773 | __le16 fileLinkCount; |
774 | uint8_t recordFormat; | 774 | uint8_t recordFormat; |
775 | uint8_t recordDisplayAttr; | 775 | uint8_t recordDisplayAttr; |
776 | __le32 recordLength; | 776 | __le32 recordLength; |
777 | __le64 informationLength; | 777 | __le64 informationLength; |
778 | __le64 objectSize; | 778 | __le64 objectSize; |
779 | __le64 logicalBlocksRecorded; | 779 | __le64 logicalBlocksRecorded; |
780 | timestamp accessTime; | 780 | struct timestamp accessTime; |
781 | timestamp modificationTime; | 781 | struct timestamp modificationTime; |
782 | timestamp createTime; | 782 | struct timestamp createTime; |
783 | timestamp attrTime; | 783 | struct timestamp attrTime; |
784 | __le32 checkpoint; | 784 | __le32 checkpoint; |
785 | __le32 reserved; | 785 | __le32 reserved; |
786 | long_ad extendedAttrICB; | 786 | struct long_ad extendedAttrICB; |
787 | long_ad streamDirectoryICB; | 787 | struct long_ad streamDirectoryICB; |
788 | regid impIdent; | 788 | struct regid impIdent; |
789 | __le64 uniqueID; | 789 | __le64 uniqueID; |
790 | __le32 lengthExtendedAttr; | 790 | __le32 lengthExtendedAttr; |
791 | __le32 lengthAllocDescs; | 791 | __le32 lengthAllocDescs; |
792 | uint8_t extendedAttr[0]; | 792 | uint8_t extendedAttr[0]; |
793 | uint8_t allocDescs[0]; | 793 | uint8_t allocDescs[0]; |
794 | } __attribute__ ((packed)); | 794 | } __attribute__ ((packed)); |
795 | 795 | ||
796 | #endif /* _ECMA_167_H */ | 796 | #endif /* _ECMA_167_H */ |
diff --git a/fs/udf/ialloc.c b/fs/udf/ialloc.c index 47dbe5613f90..c10fa39f97e2 100644 --- a/fs/udf/ialloc.c +++ b/fs/udf/ialloc.c | |||
@@ -49,12 +49,11 @@ void udf_free_inode(struct inode *inode) | |||
49 | le32_add_cpu(&lvidiu->numDirs, -1); | 49 | le32_add_cpu(&lvidiu->numDirs, -1); |
50 | else | 50 | else |
51 | le32_add_cpu(&lvidiu->numFiles, -1); | 51 | le32_add_cpu(&lvidiu->numFiles, -1); |
52 | 52 | udf_updated_lvid(sb); | |
53 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
54 | } | 53 | } |
55 | mutex_unlock(&sbi->s_alloc_mutex); | 54 | mutex_unlock(&sbi->s_alloc_mutex); |
56 | 55 | ||
57 | udf_free_blocks(sb, NULL, UDF_I(inode)->i_location, 0, 1); | 56 | udf_free_blocks(sb, NULL, &UDF_I(inode)->i_location, 0, 1); |
58 | } | 57 | } |
59 | 58 | ||
60 | struct inode *udf_new_inode(struct inode *dir, int mode, int *err) | 59 | struct inode *udf_new_inode(struct inode *dir, int mode, int *err) |
@@ -122,7 +121,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) | |||
122 | if (!(++uniqueID & 0x00000000FFFFFFFFUL)) | 121 | if (!(++uniqueID & 0x00000000FFFFFFFFUL)) |
123 | uniqueID += 16; | 122 | uniqueID += 16; |
124 | lvhd->uniqueID = cpu_to_le64(uniqueID); | 123 | lvhd->uniqueID = cpu_to_le64(uniqueID); |
125 | mark_buffer_dirty(sbi->s_lvid_bh); | 124 | udf_updated_lvid(sb); |
126 | } | 125 | } |
127 | mutex_unlock(&sbi->s_alloc_mutex); | 126 | mutex_unlock(&sbi->s_alloc_mutex); |
128 | inode->i_mode = mode; | 127 | inode->i_mode = mode; |
@@ -138,7 +137,7 @@ struct inode *udf_new_inode(struct inode *dir, int mode, int *err) | |||
138 | iinfo->i_location.logicalBlockNum = block; | 137 | iinfo->i_location.logicalBlockNum = block; |
139 | iinfo->i_location.partitionReferenceNum = | 138 | iinfo->i_location.partitionReferenceNum = |
140 | dinfo->i_location.partitionReferenceNum; | 139 | dinfo->i_location.partitionReferenceNum; |
141 | inode->i_ino = udf_get_lb_pblock(sb, iinfo->i_location, 0); | 140 | inode->i_ino = udf_get_lb_pblock(sb, &iinfo->i_location, 0); |
142 | inode->i_blocks = 0; | 141 | inode->i_blocks = 0; |
143 | iinfo->i_lenEAttr = 0; | 142 | iinfo->i_lenEAttr = 0; |
144 | iinfo->i_lenAlloc = 0; | 143 | iinfo->i_lenAlloc = 0; |
diff --git a/fs/udf/inode.c b/fs/udf/inode.c index 30ebde490f7f..e7533f785636 100644 --- a/fs/udf/inode.c +++ b/fs/udf/inode.c | |||
@@ -55,15 +55,15 @@ static int udf_alloc_i_data(struct inode *inode, size_t size); | |||
55 | static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, | 55 | static struct buffer_head *inode_getblk(struct inode *, sector_t, int *, |
56 | sector_t *, int *); | 56 | sector_t *, int *); |
57 | static int8_t udf_insert_aext(struct inode *, struct extent_position, | 57 | static int8_t udf_insert_aext(struct inode *, struct extent_position, |
58 | kernel_lb_addr, uint32_t); | 58 | struct kernel_lb_addr, uint32_t); |
59 | static void udf_split_extents(struct inode *, int *, int, int, | 59 | static void udf_split_extents(struct inode *, int *, int, int, |
60 | kernel_long_ad[EXTENT_MERGE_SIZE], int *); | 60 | struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); |
61 | static void udf_prealloc_extents(struct inode *, int, int, | 61 | static void udf_prealloc_extents(struct inode *, int, int, |
62 | kernel_long_ad[EXTENT_MERGE_SIZE], int *); | 62 | struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); |
63 | static void udf_merge_extents(struct inode *, | 63 | static void udf_merge_extents(struct inode *, |
64 | kernel_long_ad[EXTENT_MERGE_SIZE], int *); | 64 | struct kernel_long_ad[EXTENT_MERGE_SIZE], int *); |
65 | static void udf_update_extents(struct inode *, | 65 | static void udf_update_extents(struct inode *, |
66 | kernel_long_ad[EXTENT_MERGE_SIZE], int, int, | 66 | struct kernel_long_ad[EXTENT_MERGE_SIZE], int, int, |
67 | struct extent_position *); | 67 | struct extent_position *); |
68 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); | 68 | static int udf_get_block(struct inode *, sector_t, struct buffer_head *, int); |
69 | 69 | ||
@@ -200,7 +200,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, | |||
200 | { | 200 | { |
201 | int newblock; | 201 | int newblock; |
202 | struct buffer_head *dbh = NULL; | 202 | struct buffer_head *dbh = NULL; |
203 | kernel_lb_addr eloc; | 203 | struct kernel_lb_addr eloc; |
204 | uint32_t elen; | 204 | uint32_t elen; |
205 | uint8_t alloctype; | 205 | uint8_t alloctype; |
206 | struct extent_position epos; | 206 | struct extent_position epos; |
@@ -281,7 +281,7 @@ struct buffer_head *udf_expand_dir_adinicb(struct inode *inode, int *block, | |||
281 | epos.bh = NULL; | 281 | epos.bh = NULL; |
282 | epos.block = iinfo->i_location; | 282 | epos.block = iinfo->i_location; |
283 | epos.offset = udf_file_entry_alloc_offset(inode); | 283 | epos.offset = udf_file_entry_alloc_offset(inode); |
284 | udf_add_aext(inode, &epos, eloc, elen, 0); | 284 | udf_add_aext(inode, &epos, &eloc, elen, 0); |
285 | /* UniqueID stuff */ | 285 | /* UniqueID stuff */ |
286 | 286 | ||
287 | brelse(epos.bh); | 287 | brelse(epos.bh); |
@@ -359,12 +359,12 @@ static struct buffer_head *udf_getblk(struct inode *inode, long block, | |||
359 | 359 | ||
360 | /* Extend the file by 'blocks' blocks, return the number of extents added */ | 360 | /* Extend the file by 'blocks' blocks, return the number of extents added */ |
361 | int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | 361 | int udf_extend_file(struct inode *inode, struct extent_position *last_pos, |
362 | kernel_long_ad *last_ext, sector_t blocks) | 362 | struct kernel_long_ad *last_ext, sector_t blocks) |
363 | { | 363 | { |
364 | sector_t add; | 364 | sector_t add; |
365 | int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); | 365 | int count = 0, fake = !(last_ext->extLength & UDF_EXTENT_LENGTH_MASK); |
366 | struct super_block *sb = inode->i_sb; | 366 | struct super_block *sb = inode->i_sb; |
367 | kernel_lb_addr prealloc_loc = {}; | 367 | struct kernel_lb_addr prealloc_loc = {}; |
368 | int prealloc_len = 0; | 368 | int prealloc_len = 0; |
369 | struct udf_inode_info *iinfo; | 369 | struct udf_inode_info *iinfo; |
370 | 370 | ||
@@ -411,11 +411,11 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | |||
411 | } | 411 | } |
412 | 412 | ||
413 | if (fake) { | 413 | if (fake) { |
414 | udf_add_aext(inode, last_pos, last_ext->extLocation, | 414 | udf_add_aext(inode, last_pos, &last_ext->extLocation, |
415 | last_ext->extLength, 1); | 415 | last_ext->extLength, 1); |
416 | count++; | 416 | count++; |
417 | } else | 417 | } else |
418 | udf_write_aext(inode, last_pos, last_ext->extLocation, | 418 | udf_write_aext(inode, last_pos, &last_ext->extLocation, |
419 | last_ext->extLength, 1); | 419 | last_ext->extLength, 1); |
420 | 420 | ||
421 | /* Managed to do everything necessary? */ | 421 | /* Managed to do everything necessary? */ |
@@ -432,7 +432,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | |||
432 | /* Create enough extents to cover the whole hole */ | 432 | /* Create enough extents to cover the whole hole */ |
433 | while (blocks > add) { | 433 | while (blocks > add) { |
434 | blocks -= add; | 434 | blocks -= add; |
435 | if (udf_add_aext(inode, last_pos, last_ext->extLocation, | 435 | if (udf_add_aext(inode, last_pos, &last_ext->extLocation, |
436 | last_ext->extLength, 1) == -1) | 436 | last_ext->extLength, 1) == -1) |
437 | return -1; | 437 | return -1; |
438 | count++; | 438 | count++; |
@@ -440,7 +440,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | |||
440 | if (blocks) { | 440 | if (blocks) { |
441 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | 441 | last_ext->extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | |
442 | (blocks << sb->s_blocksize_bits); | 442 | (blocks << sb->s_blocksize_bits); |
443 | if (udf_add_aext(inode, last_pos, last_ext->extLocation, | 443 | if (udf_add_aext(inode, last_pos, &last_ext->extLocation, |
444 | last_ext->extLength, 1) == -1) | 444 | last_ext->extLength, 1) == -1) |
445 | return -1; | 445 | return -1; |
446 | count++; | 446 | count++; |
@@ -449,7 +449,7 @@ int udf_extend_file(struct inode *inode, struct extent_position *last_pos, | |||
449 | out: | 449 | out: |
450 | /* Do we have some preallocated blocks saved? */ | 450 | /* Do we have some preallocated blocks saved? */ |
451 | if (prealloc_len) { | 451 | if (prealloc_len) { |
452 | if (udf_add_aext(inode, last_pos, prealloc_loc, | 452 | if (udf_add_aext(inode, last_pos, &prealloc_loc, |
453 | prealloc_len, 1) == -1) | 453 | prealloc_len, 1) == -1) |
454 | return -1; | 454 | return -1; |
455 | last_ext->extLocation = prealloc_loc; | 455 | last_ext->extLocation = prealloc_loc; |
@@ -459,9 +459,9 @@ out: | |||
459 | 459 | ||
460 | /* last_pos should point to the last written extent... */ | 460 | /* last_pos should point to the last written extent... */ |
461 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 461 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
462 | last_pos->offset -= sizeof(short_ad); | 462 | last_pos->offset -= sizeof(struct short_ad); |
463 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 463 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
464 | last_pos->offset -= sizeof(long_ad); | 464 | last_pos->offset -= sizeof(struct long_ad); |
465 | else | 465 | else |
466 | return -1; | 466 | return -1; |
467 | 467 | ||
@@ -473,11 +473,11 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
473 | { | 473 | { |
474 | static sector_t last_block; | 474 | static sector_t last_block; |
475 | struct buffer_head *result = NULL; | 475 | struct buffer_head *result = NULL; |
476 | kernel_long_ad laarr[EXTENT_MERGE_SIZE]; | 476 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE]; |
477 | struct extent_position prev_epos, cur_epos, next_epos; | 477 | struct extent_position prev_epos, cur_epos, next_epos; |
478 | int count = 0, startnum = 0, endnum = 0; | 478 | int count = 0, startnum = 0, endnum = 0; |
479 | uint32_t elen = 0, tmpelen; | 479 | uint32_t elen = 0, tmpelen; |
480 | kernel_lb_addr eloc, tmpeloc; | 480 | struct kernel_lb_addr eloc, tmpeloc; |
481 | int c = 1; | 481 | int c = 1; |
482 | loff_t lbcount = 0, b_off = 0; | 482 | loff_t lbcount = 0, b_off = 0; |
483 | uint32_t newblocknum, newblock; | 483 | uint32_t newblocknum, newblock; |
@@ -550,12 +550,12 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
550 | elen = EXT_RECORDED_ALLOCATED | | 550 | elen = EXT_RECORDED_ALLOCATED | |
551 | ((elen + inode->i_sb->s_blocksize - 1) & | 551 | ((elen + inode->i_sb->s_blocksize - 1) & |
552 | ~(inode->i_sb->s_blocksize - 1)); | 552 | ~(inode->i_sb->s_blocksize - 1)); |
553 | etype = udf_write_aext(inode, &cur_epos, eloc, elen, 1); | 553 | etype = udf_write_aext(inode, &cur_epos, &eloc, elen, 1); |
554 | } | 554 | } |
555 | brelse(prev_epos.bh); | 555 | brelse(prev_epos.bh); |
556 | brelse(cur_epos.bh); | 556 | brelse(cur_epos.bh); |
557 | brelse(next_epos.bh); | 557 | brelse(next_epos.bh); |
558 | newblock = udf_get_lb_pblock(inode->i_sb, eloc, offset); | 558 | newblock = udf_get_lb_pblock(inode->i_sb, &eloc, offset); |
559 | *phys = newblock; | 559 | *phys = newblock; |
560 | return NULL; | 560 | return NULL; |
561 | } | 561 | } |
@@ -572,7 +572,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
572 | } else { | 572 | } else { |
573 | /* Create a fake extent when there's not one */ | 573 | /* Create a fake extent when there's not one */ |
574 | memset(&laarr[0].extLocation, 0x00, | 574 | memset(&laarr[0].extLocation, 0x00, |
575 | sizeof(kernel_lb_addr)); | 575 | sizeof(struct kernel_lb_addr)); |
576 | laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; | 576 | laarr[0].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED; |
577 | /* Will udf_extend_file() create real extent from | 577 | /* Will udf_extend_file() create real extent from |
578 | a fake one? */ | 578 | a fake one? */ |
@@ -602,7 +602,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
602 | laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | | 602 | laarr[c].extLength = EXT_NOT_RECORDED_NOT_ALLOCATED | |
603 | inode->i_sb->s_blocksize; | 603 | inode->i_sb->s_blocksize; |
604 | memset(&laarr[c].extLocation, 0x00, | 604 | memset(&laarr[c].extLocation, 0x00, |
605 | sizeof(kernel_lb_addr)); | 605 | sizeof(struct kernel_lb_addr)); |
606 | count++; | 606 | count++; |
607 | endnum++; | 607 | endnum++; |
608 | } | 608 | } |
@@ -699,7 +699,7 @@ static struct buffer_head *inode_getblk(struct inode *inode, sector_t block, | |||
699 | 699 | ||
700 | static void udf_split_extents(struct inode *inode, int *c, int offset, | 700 | static void udf_split_extents(struct inode *inode, int *c, int offset, |
701 | int newblocknum, | 701 | int newblocknum, |
702 | kernel_long_ad laarr[EXTENT_MERGE_SIZE], | 702 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], |
703 | int *endnum) | 703 | int *endnum) |
704 | { | 704 | { |
705 | unsigned long blocksize = inode->i_sb->s_blocksize; | 705 | unsigned long blocksize = inode->i_sb->s_blocksize; |
@@ -726,7 +726,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, | |||
726 | if (offset) { | 726 | if (offset) { |
727 | if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { | 727 | if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { |
728 | udf_free_blocks(inode->i_sb, inode, | 728 | udf_free_blocks(inode->i_sb, inode, |
729 | laarr[curr].extLocation, | 729 | &laarr[curr].extLocation, |
730 | 0, offset); | 730 | 0, offset); |
731 | laarr[curr].extLength = | 731 | laarr[curr].extLength = |
732 | EXT_NOT_RECORDED_NOT_ALLOCATED | | 732 | EXT_NOT_RECORDED_NOT_ALLOCATED | |
@@ -763,7 +763,7 @@ static void udf_split_extents(struct inode *inode, int *c, int offset, | |||
763 | } | 763 | } |
764 | 764 | ||
765 | static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, | 765 | static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, |
766 | kernel_long_ad laarr[EXTENT_MERGE_SIZE], | 766 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], |
767 | int *endnum) | 767 | int *endnum) |
768 | { | 768 | { |
769 | int start, length = 0, currlength = 0, i; | 769 | int start, length = 0, currlength = 0, i; |
@@ -817,7 +817,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, | |||
817 | inode->i_sb->s_blocksize_bits); | 817 | inode->i_sb->s_blocksize_bits); |
818 | else { | 818 | else { |
819 | memmove(&laarr[c + 2], &laarr[c + 1], | 819 | memmove(&laarr[c + 2], &laarr[c + 1], |
820 | sizeof(long_ad) * (*endnum - (c + 1))); | 820 | sizeof(struct long_ad) * (*endnum - (c + 1))); |
821 | (*endnum)++; | 821 | (*endnum)++; |
822 | laarr[c + 1].extLocation.logicalBlockNum = next; | 822 | laarr[c + 1].extLocation.logicalBlockNum = next; |
823 | laarr[c + 1].extLocation.partitionReferenceNum = | 823 | laarr[c + 1].extLocation.partitionReferenceNum = |
@@ -846,7 +846,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, | |||
846 | if (*endnum > (i + 1)) | 846 | if (*endnum > (i + 1)) |
847 | memmove(&laarr[i], | 847 | memmove(&laarr[i], |
848 | &laarr[i + 1], | 848 | &laarr[i + 1], |
849 | sizeof(long_ad) * | 849 | sizeof(struct long_ad) * |
850 | (*endnum - (i + 1))); | 850 | (*endnum - (i + 1))); |
851 | i--; | 851 | i--; |
852 | (*endnum)--; | 852 | (*endnum)--; |
@@ -859,7 +859,7 @@ static void udf_prealloc_extents(struct inode *inode, int c, int lastblock, | |||
859 | } | 859 | } |
860 | 860 | ||
861 | static void udf_merge_extents(struct inode *inode, | 861 | static void udf_merge_extents(struct inode *inode, |
862 | kernel_long_ad laarr[EXTENT_MERGE_SIZE], | 862 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], |
863 | int *endnum) | 863 | int *endnum) |
864 | { | 864 | { |
865 | int i; | 865 | int i; |
@@ -867,8 +867,8 @@ static void udf_merge_extents(struct inode *inode, | |||
867 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 867 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
868 | 868 | ||
869 | for (i = 0; i < (*endnum - 1); i++) { | 869 | for (i = 0; i < (*endnum - 1); i++) { |
870 | kernel_long_ad *li /*l[i]*/ = &laarr[i]; | 870 | struct kernel_long_ad *li /*l[i]*/ = &laarr[i]; |
871 | kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1]; | 871 | struct kernel_long_ad *lip1 /*l[i plus 1]*/ = &laarr[i + 1]; |
872 | 872 | ||
873 | if (((li->extLength >> 30) == (lip1->extLength >> 30)) && | 873 | if (((li->extLength >> 30) == (lip1->extLength >> 30)) && |
874 | (((li->extLength >> 30) == | 874 | (((li->extLength >> 30) == |
@@ -902,7 +902,7 @@ static void udf_merge_extents(struct inode *inode, | |||
902 | blocksize - 1) & ~(blocksize - 1)); | 902 | blocksize - 1) & ~(blocksize - 1)); |
903 | if (*endnum > (i + 2)) | 903 | if (*endnum > (i + 2)) |
904 | memmove(&laarr[i + 1], &laarr[i + 2], | 904 | memmove(&laarr[i + 1], &laarr[i + 2], |
905 | sizeof(long_ad) * | 905 | sizeof(struct long_ad) * |
906 | (*endnum - (i + 2))); | 906 | (*endnum - (i + 2))); |
907 | i--; | 907 | i--; |
908 | (*endnum)--; | 908 | (*endnum)--; |
@@ -911,7 +911,7 @@ static void udf_merge_extents(struct inode *inode, | |||
911 | (EXT_NOT_RECORDED_ALLOCATED >> 30)) && | 911 | (EXT_NOT_RECORDED_ALLOCATED >> 30)) && |
912 | ((lip1->extLength >> 30) == | 912 | ((lip1->extLength >> 30) == |
913 | (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) { | 913 | (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30))) { |
914 | udf_free_blocks(inode->i_sb, inode, li->extLocation, 0, | 914 | udf_free_blocks(inode->i_sb, inode, &li->extLocation, 0, |
915 | ((li->extLength & | 915 | ((li->extLength & |
916 | UDF_EXTENT_LENGTH_MASK) + | 916 | UDF_EXTENT_LENGTH_MASK) + |
917 | blocksize - 1) >> blocksize_bits); | 917 | blocksize - 1) >> blocksize_bits); |
@@ -937,7 +937,7 @@ static void udf_merge_extents(struct inode *inode, | |||
937 | blocksize - 1) & ~(blocksize - 1)); | 937 | blocksize - 1) & ~(blocksize - 1)); |
938 | if (*endnum > (i + 2)) | 938 | if (*endnum > (i + 2)) |
939 | memmove(&laarr[i + 1], &laarr[i + 2], | 939 | memmove(&laarr[i + 1], &laarr[i + 2], |
940 | sizeof(long_ad) * | 940 | sizeof(struct long_ad) * |
941 | (*endnum - (i + 2))); | 941 | (*endnum - (i + 2))); |
942 | i--; | 942 | i--; |
943 | (*endnum)--; | 943 | (*endnum)--; |
@@ -945,7 +945,7 @@ static void udf_merge_extents(struct inode *inode, | |||
945 | } else if ((li->extLength >> 30) == | 945 | } else if ((li->extLength >> 30) == |
946 | (EXT_NOT_RECORDED_ALLOCATED >> 30)) { | 946 | (EXT_NOT_RECORDED_ALLOCATED >> 30)) { |
947 | udf_free_blocks(inode->i_sb, inode, | 947 | udf_free_blocks(inode->i_sb, inode, |
948 | li->extLocation, 0, | 948 | &li->extLocation, 0, |
949 | ((li->extLength & | 949 | ((li->extLength & |
950 | UDF_EXTENT_LENGTH_MASK) + | 950 | UDF_EXTENT_LENGTH_MASK) + |
951 | blocksize - 1) >> blocksize_bits); | 951 | blocksize - 1) >> blocksize_bits); |
@@ -959,12 +959,12 @@ static void udf_merge_extents(struct inode *inode, | |||
959 | } | 959 | } |
960 | 960 | ||
961 | static void udf_update_extents(struct inode *inode, | 961 | static void udf_update_extents(struct inode *inode, |
962 | kernel_long_ad laarr[EXTENT_MERGE_SIZE], | 962 | struct kernel_long_ad laarr[EXTENT_MERGE_SIZE], |
963 | int startnum, int endnum, | 963 | int startnum, int endnum, |
964 | struct extent_position *epos) | 964 | struct extent_position *epos) |
965 | { | 965 | { |
966 | int start = 0, i; | 966 | int start = 0, i; |
967 | kernel_lb_addr tmploc; | 967 | struct kernel_lb_addr tmploc; |
968 | uint32_t tmplen; | 968 | uint32_t tmplen; |
969 | 969 | ||
970 | if (startnum > endnum) { | 970 | if (startnum > endnum) { |
@@ -983,7 +983,7 @@ static void udf_update_extents(struct inode *inode, | |||
983 | 983 | ||
984 | for (i = start; i < endnum; i++) { | 984 | for (i = start; i < endnum; i++) { |
985 | udf_next_aext(inode, epos, &tmploc, &tmplen, 0); | 985 | udf_next_aext(inode, epos, &tmploc, &tmplen, 0); |
986 | udf_write_aext(inode, epos, laarr[i].extLocation, | 986 | udf_write_aext(inode, epos, &laarr[i].extLocation, |
987 | laarr[i].extLength, 1); | 987 | laarr[i].extLength, 1); |
988 | } | 988 | } |
989 | } | 989 | } |
@@ -1076,7 +1076,7 @@ static void __udf_read_inode(struct inode *inode) | |||
1076 | * i_nlink = 1 | 1076 | * i_nlink = 1 |
1077 | * i_op = NULL; | 1077 | * i_op = NULL; |
1078 | */ | 1078 | */ |
1079 | bh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 0, &ident); | 1079 | bh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 0, &ident); |
1080 | if (!bh) { | 1080 | if (!bh) { |
1081 | printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n", | 1081 | printk(KERN_ERR "udf: udf_read_inode(ino %ld) failed !bh\n", |
1082 | inode->i_ino); | 1082 | inode->i_ino); |
@@ -1098,24 +1098,24 @@ static void __udf_read_inode(struct inode *inode) | |||
1098 | if (fe->icbTag.strategyType == cpu_to_le16(4096)) { | 1098 | if (fe->icbTag.strategyType == cpu_to_le16(4096)) { |
1099 | struct buffer_head *ibh; | 1099 | struct buffer_head *ibh; |
1100 | 1100 | ||
1101 | ibh = udf_read_ptagged(inode->i_sb, iinfo->i_location, 1, | 1101 | ibh = udf_read_ptagged(inode->i_sb, &iinfo->i_location, 1, |
1102 | &ident); | 1102 | &ident); |
1103 | if (ident == TAG_IDENT_IE && ibh) { | 1103 | if (ident == TAG_IDENT_IE && ibh) { |
1104 | struct buffer_head *nbh = NULL; | 1104 | struct buffer_head *nbh = NULL; |
1105 | kernel_lb_addr loc; | 1105 | struct kernel_lb_addr loc; |
1106 | struct indirectEntry *ie; | 1106 | struct indirectEntry *ie; |
1107 | 1107 | ||
1108 | ie = (struct indirectEntry *)ibh->b_data; | 1108 | ie = (struct indirectEntry *)ibh->b_data; |
1109 | loc = lelb_to_cpu(ie->indirectICB.extLocation); | 1109 | loc = lelb_to_cpu(ie->indirectICB.extLocation); |
1110 | 1110 | ||
1111 | if (ie->indirectICB.extLength && | 1111 | if (ie->indirectICB.extLength && |
1112 | (nbh = udf_read_ptagged(inode->i_sb, loc, 0, | 1112 | (nbh = udf_read_ptagged(inode->i_sb, &loc, 0, |
1113 | &ident))) { | 1113 | &ident))) { |
1114 | if (ident == TAG_IDENT_FE || | 1114 | if (ident == TAG_IDENT_FE || |
1115 | ident == TAG_IDENT_EFE) { | 1115 | ident == TAG_IDENT_EFE) { |
1116 | memcpy(&iinfo->i_location, | 1116 | memcpy(&iinfo->i_location, |
1117 | &loc, | 1117 | &loc, |
1118 | sizeof(kernel_lb_addr)); | 1118 | sizeof(struct kernel_lb_addr)); |
1119 | brelse(bh); | 1119 | brelse(bh); |
1120 | brelse(ibh); | 1120 | brelse(ibh); |
1121 | brelse(nbh); | 1121 | brelse(nbh); |
@@ -1222,8 +1222,15 @@ static void udf_fill_inode(struct inode *inode, struct buffer_head *bh) | |||
1222 | inode->i_size = le64_to_cpu(fe->informationLength); | 1222 | inode->i_size = le64_to_cpu(fe->informationLength); |
1223 | iinfo->i_lenExtents = inode->i_size; | 1223 | iinfo->i_lenExtents = inode->i_size; |
1224 | 1224 | ||
1225 | inode->i_mode = udf_convert_permissions(fe); | 1225 | if (fe->icbTag.fileType != ICBTAG_FILE_TYPE_DIRECTORY && |
1226 | inode->i_mode &= ~UDF_SB(inode->i_sb)->s_umask; | 1226 | sbi->s_fmode != UDF_INVALID_MODE) |
1227 | inode->i_mode = sbi->s_fmode; | ||
1228 | else if (fe->icbTag.fileType == ICBTAG_FILE_TYPE_DIRECTORY && | ||
1229 | sbi->s_dmode != UDF_INVALID_MODE) | ||
1230 | inode->i_mode = sbi->s_dmode; | ||
1231 | else | ||
1232 | inode->i_mode = udf_convert_permissions(fe); | ||
1233 | inode->i_mode &= ~sbi->s_umask; | ||
1227 | 1234 | ||
1228 | if (iinfo->i_efe == 0) { | 1235 | if (iinfo->i_efe == 0) { |
1229 | inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << | 1236 | inode->i_blocks = le64_to_cpu(fe->logicalBlocksRecorded) << |
@@ -1396,7 +1403,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1396 | 1403 | ||
1397 | bh = udf_tread(inode->i_sb, | 1404 | bh = udf_tread(inode->i_sb, |
1398 | udf_get_lb_pblock(inode->i_sb, | 1405 | udf_get_lb_pblock(inode->i_sb, |
1399 | iinfo->i_location, 0)); | 1406 | &iinfo->i_location, 0)); |
1400 | if (!bh) { | 1407 | if (!bh) { |
1401 | udf_debug("bread failure\n"); | 1408 | udf_debug("bread failure\n"); |
1402 | return -EIO; | 1409 | return -EIO; |
@@ -1416,13 +1423,13 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1416 | iinfo->i_ext.i_data, inode->i_sb->s_blocksize - | 1423 | iinfo->i_ext.i_data, inode->i_sb->s_blocksize - |
1417 | sizeof(struct unallocSpaceEntry)); | 1424 | sizeof(struct unallocSpaceEntry)); |
1418 | crclen = sizeof(struct unallocSpaceEntry) + | 1425 | crclen = sizeof(struct unallocSpaceEntry) + |
1419 | iinfo->i_lenAlloc - sizeof(tag); | 1426 | iinfo->i_lenAlloc - sizeof(struct tag); |
1420 | use->descTag.tagLocation = cpu_to_le32( | 1427 | use->descTag.tagLocation = cpu_to_le32( |
1421 | iinfo->i_location. | 1428 | iinfo->i_location. |
1422 | logicalBlockNum); | 1429 | logicalBlockNum); |
1423 | use->descTag.descCRCLength = cpu_to_le16(crclen); | 1430 | use->descTag.descCRCLength = cpu_to_le16(crclen); |
1424 | use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + | 1431 | use->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)use + |
1425 | sizeof(tag), | 1432 | sizeof(struct tag), |
1426 | crclen)); | 1433 | crclen)); |
1427 | use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); | 1434 | use->descTag.tagChecksum = udf_tag_checksum(&use->descTag); |
1428 | 1435 | ||
@@ -1459,23 +1466,23 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1459 | fe->informationLength = cpu_to_le64(inode->i_size); | 1466 | fe->informationLength = cpu_to_le64(inode->i_size); |
1460 | 1467 | ||
1461 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { | 1468 | if (S_ISCHR(inode->i_mode) || S_ISBLK(inode->i_mode)) { |
1462 | regid *eid; | 1469 | struct regid *eid; |
1463 | struct deviceSpec *dsea = | 1470 | struct deviceSpec *dsea = |
1464 | (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); | 1471 | (struct deviceSpec *)udf_get_extendedattr(inode, 12, 1); |
1465 | if (!dsea) { | 1472 | if (!dsea) { |
1466 | dsea = (struct deviceSpec *) | 1473 | dsea = (struct deviceSpec *) |
1467 | udf_add_extendedattr(inode, | 1474 | udf_add_extendedattr(inode, |
1468 | sizeof(struct deviceSpec) + | 1475 | sizeof(struct deviceSpec) + |
1469 | sizeof(regid), 12, 0x3); | 1476 | sizeof(struct regid), 12, 0x3); |
1470 | dsea->attrType = cpu_to_le32(12); | 1477 | dsea->attrType = cpu_to_le32(12); |
1471 | dsea->attrSubtype = 1; | 1478 | dsea->attrSubtype = 1; |
1472 | dsea->attrLength = cpu_to_le32( | 1479 | dsea->attrLength = cpu_to_le32( |
1473 | sizeof(struct deviceSpec) + | 1480 | sizeof(struct deviceSpec) + |
1474 | sizeof(regid)); | 1481 | sizeof(struct regid)); |
1475 | dsea->impUseLength = cpu_to_le32(sizeof(regid)); | 1482 | dsea->impUseLength = cpu_to_le32(sizeof(struct regid)); |
1476 | } | 1483 | } |
1477 | eid = (regid *)dsea->impUse; | 1484 | eid = (struct regid *)dsea->impUse; |
1478 | memset(eid, 0, sizeof(regid)); | 1485 | memset(eid, 0, sizeof(struct regid)); |
1479 | strcpy(eid->ident, UDF_ID_DEVELOPER); | 1486 | strcpy(eid->ident, UDF_ID_DEVELOPER); |
1480 | eid->identSuffix[0] = UDF_OS_CLASS_UNIX; | 1487 | eid->identSuffix[0] = UDF_OS_CLASS_UNIX; |
1481 | eid->identSuffix[1] = UDF_OS_ID_LINUX; | 1488 | eid->identSuffix[1] = UDF_OS_ID_LINUX; |
@@ -1494,7 +1501,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1494 | udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime); | 1501 | udf_time_to_disk_stamp(&fe->accessTime, inode->i_atime); |
1495 | udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime); | 1502 | udf_time_to_disk_stamp(&fe->modificationTime, inode->i_mtime); |
1496 | udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime); | 1503 | udf_time_to_disk_stamp(&fe->attrTime, inode->i_ctime); |
1497 | memset(&(fe->impIdent), 0, sizeof(regid)); | 1504 | memset(&(fe->impIdent), 0, sizeof(struct regid)); |
1498 | strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); | 1505 | strcpy(fe->impIdent.ident, UDF_ID_DEVELOPER); |
1499 | fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1506 | fe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
1500 | fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1507 | fe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
@@ -1533,7 +1540,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1533 | udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime); | 1540 | udf_time_to_disk_stamp(&efe->createTime, iinfo->i_crtime); |
1534 | udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime); | 1541 | udf_time_to_disk_stamp(&efe->attrTime, inode->i_ctime); |
1535 | 1542 | ||
1536 | memset(&(efe->impIdent), 0, sizeof(regid)); | 1543 | memset(&(efe->impIdent), 0, sizeof(struct regid)); |
1537 | strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); | 1544 | strcpy(efe->impIdent.ident, UDF_ID_DEVELOPER); |
1538 | efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1545 | efe->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
1539 | efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1546 | efe->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
@@ -1584,9 +1591,9 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1584 | fe->descTag.tagLocation = cpu_to_le32( | 1591 | fe->descTag.tagLocation = cpu_to_le32( |
1585 | iinfo->i_location.logicalBlockNum); | 1592 | iinfo->i_location.logicalBlockNum); |
1586 | crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - | 1593 | crclen += iinfo->i_lenEAttr + iinfo->i_lenAlloc - |
1587 | sizeof(tag); | 1594 | sizeof(struct tag); |
1588 | fe->descTag.descCRCLength = cpu_to_le16(crclen); | 1595 | fe->descTag.descCRCLength = cpu_to_le16(crclen); |
1589 | fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(tag), | 1596 | fe->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)fe + sizeof(struct tag), |
1590 | crclen)); | 1597 | crclen)); |
1591 | fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); | 1598 | fe->descTag.tagChecksum = udf_tag_checksum(&fe->descTag); |
1592 | 1599 | ||
@@ -1606,7 +1613,7 @@ static int udf_update_inode(struct inode *inode, int do_sync) | |||
1606 | return err; | 1613 | return err; |
1607 | } | 1614 | } |
1608 | 1615 | ||
1609 | struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) | 1616 | struct inode *udf_iget(struct super_block *sb, struct kernel_lb_addr *ino) |
1610 | { | 1617 | { |
1611 | unsigned long block = udf_get_lb_pblock(sb, ino, 0); | 1618 | unsigned long block = udf_get_lb_pblock(sb, ino, 0); |
1612 | struct inode *inode = iget_locked(sb, block); | 1619 | struct inode *inode = iget_locked(sb, block); |
@@ -1615,7 +1622,7 @@ struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) | |||
1615 | return NULL; | 1622 | return NULL; |
1616 | 1623 | ||
1617 | if (inode->i_state & I_NEW) { | 1624 | if (inode->i_state & I_NEW) { |
1618 | memcpy(&UDF_I(inode)->i_location, &ino, sizeof(kernel_lb_addr)); | 1625 | memcpy(&UDF_I(inode)->i_location, ino, sizeof(struct kernel_lb_addr)); |
1619 | __udf_read_inode(inode); | 1626 | __udf_read_inode(inode); |
1620 | unlock_new_inode(inode); | 1627 | unlock_new_inode(inode); |
1621 | } | 1628 | } |
@@ -1623,10 +1630,10 @@ struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) | |||
1623 | if (is_bad_inode(inode)) | 1630 | if (is_bad_inode(inode)) |
1624 | goto out_iput; | 1631 | goto out_iput; |
1625 | 1632 | ||
1626 | if (ino.logicalBlockNum >= UDF_SB(sb)-> | 1633 | if (ino->logicalBlockNum >= UDF_SB(sb)-> |
1627 | s_partmaps[ino.partitionReferenceNum].s_partition_len) { | 1634 | s_partmaps[ino->partitionReferenceNum].s_partition_len) { |
1628 | udf_debug("block=%d, partition=%d out of range\n", | 1635 | udf_debug("block=%d, partition=%d out of range\n", |
1629 | ino.logicalBlockNum, ino.partitionReferenceNum); | 1636 | ino->logicalBlockNum, ino->partitionReferenceNum); |
1630 | make_bad_inode(inode); | 1637 | make_bad_inode(inode); |
1631 | goto out_iput; | 1638 | goto out_iput; |
1632 | } | 1639 | } |
@@ -1639,11 +1646,11 @@ struct inode *udf_iget(struct super_block *sb, kernel_lb_addr ino) | |||
1639 | } | 1646 | } |
1640 | 1647 | ||
1641 | int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | 1648 | int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, |
1642 | kernel_lb_addr eloc, uint32_t elen, int inc) | 1649 | struct kernel_lb_addr *eloc, uint32_t elen, int inc) |
1643 | { | 1650 | { |
1644 | int adsize; | 1651 | int adsize; |
1645 | short_ad *sad = NULL; | 1652 | struct short_ad *sad = NULL; |
1646 | long_ad *lad = NULL; | 1653 | struct long_ad *lad = NULL; |
1647 | struct allocExtDesc *aed; | 1654 | struct allocExtDesc *aed; |
1648 | int8_t etype; | 1655 | int8_t etype; |
1649 | uint8_t *ptr; | 1656 | uint8_t *ptr; |
@@ -1657,9 +1664,9 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1657 | ptr = epos->bh->b_data + epos->offset; | 1664 | ptr = epos->bh->b_data + epos->offset; |
1658 | 1665 | ||
1659 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 1666 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
1660 | adsize = sizeof(short_ad); | 1667 | adsize = sizeof(struct short_ad); |
1661 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 1668 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
1662 | adsize = sizeof(long_ad); | 1669 | adsize = sizeof(struct long_ad); |
1663 | else | 1670 | else |
1664 | return -1; | 1671 | return -1; |
1665 | 1672 | ||
@@ -1667,7 +1674,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1667 | char *sptr, *dptr; | 1674 | char *sptr, *dptr; |
1668 | struct buffer_head *nbh; | 1675 | struct buffer_head *nbh; |
1669 | int err, loffset; | 1676 | int err, loffset; |
1670 | kernel_lb_addr obloc = epos->block; | 1677 | struct kernel_lb_addr obloc = epos->block; |
1671 | 1678 | ||
1672 | epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL, | 1679 | epos->block.logicalBlockNum = udf_new_block(inode->i_sb, NULL, |
1673 | obloc.partitionReferenceNum, | 1680 | obloc.partitionReferenceNum, |
@@ -1675,7 +1682,7 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1675 | if (!epos->block.logicalBlockNum) | 1682 | if (!epos->block.logicalBlockNum) |
1676 | return -1; | 1683 | return -1; |
1677 | nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, | 1684 | nbh = udf_tgetblk(inode->i_sb, udf_get_lb_pblock(inode->i_sb, |
1678 | epos->block, | 1685 | &epos->block, |
1679 | 0)); | 1686 | 0)); |
1680 | if (!nbh) | 1687 | if (!nbh) |
1681 | return -1; | 1688 | return -1; |
@@ -1712,20 +1719,20 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1712 | } | 1719 | } |
1713 | if (UDF_SB(inode->i_sb)->s_udfrev >= 0x0200) | 1720 | if (UDF_SB(inode->i_sb)->s_udfrev >= 0x0200) |
1714 | udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1, | 1721 | udf_new_tag(nbh->b_data, TAG_IDENT_AED, 3, 1, |
1715 | epos->block.logicalBlockNum, sizeof(tag)); | 1722 | epos->block.logicalBlockNum, sizeof(struct tag)); |
1716 | else | 1723 | else |
1717 | udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1, | 1724 | udf_new_tag(nbh->b_data, TAG_IDENT_AED, 2, 1, |
1718 | epos->block.logicalBlockNum, sizeof(tag)); | 1725 | epos->block.logicalBlockNum, sizeof(struct tag)); |
1719 | switch (iinfo->i_alloc_type) { | 1726 | switch (iinfo->i_alloc_type) { |
1720 | case ICBTAG_FLAG_AD_SHORT: | 1727 | case ICBTAG_FLAG_AD_SHORT: |
1721 | sad = (short_ad *)sptr; | 1728 | sad = (struct short_ad *)sptr; |
1722 | sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | | 1729 | sad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | |
1723 | inode->i_sb->s_blocksize); | 1730 | inode->i_sb->s_blocksize); |
1724 | sad->extPosition = | 1731 | sad->extPosition = |
1725 | cpu_to_le32(epos->block.logicalBlockNum); | 1732 | cpu_to_le32(epos->block.logicalBlockNum); |
1726 | break; | 1733 | break; |
1727 | case ICBTAG_FLAG_AD_LONG: | 1734 | case ICBTAG_FLAG_AD_LONG: |
1728 | lad = (long_ad *)sptr; | 1735 | lad = (struct long_ad *)sptr; |
1729 | lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | | 1736 | lad->extLength = cpu_to_le32(EXT_NEXT_EXTENT_ALLOCDECS | |
1730 | inode->i_sb->s_blocksize); | 1737 | inode->i_sb->s_blocksize); |
1731 | lad->extLocation = cpu_to_lelb(epos->block); | 1738 | lad->extLocation = cpu_to_lelb(epos->block); |
@@ -1769,12 +1776,12 @@ int8_t udf_add_aext(struct inode *inode, struct extent_position *epos, | |||
1769 | } | 1776 | } |
1770 | 1777 | ||
1771 | int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, | 1778 | int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, |
1772 | kernel_lb_addr eloc, uint32_t elen, int inc) | 1779 | struct kernel_lb_addr *eloc, uint32_t elen, int inc) |
1773 | { | 1780 | { |
1774 | int adsize; | 1781 | int adsize; |
1775 | uint8_t *ptr; | 1782 | uint8_t *ptr; |
1776 | short_ad *sad; | 1783 | struct short_ad *sad; |
1777 | long_ad *lad; | 1784 | struct long_ad *lad; |
1778 | struct udf_inode_info *iinfo = UDF_I(inode); | 1785 | struct udf_inode_info *iinfo = UDF_I(inode); |
1779 | 1786 | ||
1780 | if (!epos->bh) | 1787 | if (!epos->bh) |
@@ -1786,17 +1793,17 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, | |||
1786 | 1793 | ||
1787 | switch (iinfo->i_alloc_type) { | 1794 | switch (iinfo->i_alloc_type) { |
1788 | case ICBTAG_FLAG_AD_SHORT: | 1795 | case ICBTAG_FLAG_AD_SHORT: |
1789 | sad = (short_ad *)ptr; | 1796 | sad = (struct short_ad *)ptr; |
1790 | sad->extLength = cpu_to_le32(elen); | 1797 | sad->extLength = cpu_to_le32(elen); |
1791 | sad->extPosition = cpu_to_le32(eloc.logicalBlockNum); | 1798 | sad->extPosition = cpu_to_le32(eloc->logicalBlockNum); |
1792 | adsize = sizeof(short_ad); | 1799 | adsize = sizeof(struct short_ad); |
1793 | break; | 1800 | break; |
1794 | case ICBTAG_FLAG_AD_LONG: | 1801 | case ICBTAG_FLAG_AD_LONG: |
1795 | lad = (long_ad *)ptr; | 1802 | lad = (struct long_ad *)ptr; |
1796 | lad->extLength = cpu_to_le32(elen); | 1803 | lad->extLength = cpu_to_le32(elen); |
1797 | lad->extLocation = cpu_to_lelb(eloc); | 1804 | lad->extLocation = cpu_to_lelb(*eloc); |
1798 | memset(lad->impUse, 0x00, sizeof(lad->impUse)); | 1805 | memset(lad->impUse, 0x00, sizeof(lad->impUse)); |
1799 | adsize = sizeof(long_ad); | 1806 | adsize = sizeof(struct long_ad); |
1800 | break; | 1807 | break; |
1801 | default: | 1808 | default: |
1802 | return -1; | 1809 | return -1; |
@@ -1823,7 +1830,7 @@ int8_t udf_write_aext(struct inode *inode, struct extent_position *epos, | |||
1823 | } | 1830 | } |
1824 | 1831 | ||
1825 | int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, | 1832 | int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, |
1826 | kernel_lb_addr *eloc, uint32_t *elen, int inc) | 1833 | struct kernel_lb_addr *eloc, uint32_t *elen, int inc) |
1827 | { | 1834 | { |
1828 | int8_t etype; | 1835 | int8_t etype; |
1829 | 1836 | ||
@@ -1833,7 +1840,7 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, | |||
1833 | epos->block = *eloc; | 1840 | epos->block = *eloc; |
1834 | epos->offset = sizeof(struct allocExtDesc); | 1841 | epos->offset = sizeof(struct allocExtDesc); |
1835 | brelse(epos->bh); | 1842 | brelse(epos->bh); |
1836 | block = udf_get_lb_pblock(inode->i_sb, epos->block, 0); | 1843 | block = udf_get_lb_pblock(inode->i_sb, &epos->block, 0); |
1837 | epos->bh = udf_tread(inode->i_sb, block); | 1844 | epos->bh = udf_tread(inode->i_sb, block); |
1838 | if (!epos->bh) { | 1845 | if (!epos->bh) { |
1839 | udf_debug("reading block %d failed!\n", block); | 1846 | udf_debug("reading block %d failed!\n", block); |
@@ -1845,13 +1852,13 @@ int8_t udf_next_aext(struct inode *inode, struct extent_position *epos, | |||
1845 | } | 1852 | } |
1846 | 1853 | ||
1847 | int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, | 1854 | int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, |
1848 | kernel_lb_addr *eloc, uint32_t *elen, int inc) | 1855 | struct kernel_lb_addr *eloc, uint32_t *elen, int inc) |
1849 | { | 1856 | { |
1850 | int alen; | 1857 | int alen; |
1851 | int8_t etype; | 1858 | int8_t etype; |
1852 | uint8_t *ptr; | 1859 | uint8_t *ptr; |
1853 | short_ad *sad; | 1860 | struct short_ad *sad; |
1854 | long_ad *lad; | 1861 | struct long_ad *lad; |
1855 | struct udf_inode_info *iinfo = UDF_I(inode); | 1862 | struct udf_inode_info *iinfo = UDF_I(inode); |
1856 | 1863 | ||
1857 | if (!epos->bh) { | 1864 | if (!epos->bh) { |
@@ -1900,9 +1907,9 @@ int8_t udf_current_aext(struct inode *inode, struct extent_position *epos, | |||
1900 | } | 1907 | } |
1901 | 1908 | ||
1902 | static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, | 1909 | static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, |
1903 | kernel_lb_addr neloc, uint32_t nelen) | 1910 | struct kernel_lb_addr neloc, uint32_t nelen) |
1904 | { | 1911 | { |
1905 | kernel_lb_addr oeloc; | 1912 | struct kernel_lb_addr oeloc; |
1906 | uint32_t oelen; | 1913 | uint32_t oelen; |
1907 | int8_t etype; | 1914 | int8_t etype; |
1908 | 1915 | ||
@@ -1910,18 +1917,18 @@ static int8_t udf_insert_aext(struct inode *inode, struct extent_position epos, | |||
1910 | get_bh(epos.bh); | 1917 | get_bh(epos.bh); |
1911 | 1918 | ||
1912 | while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) { | 1919 | while ((etype = udf_next_aext(inode, &epos, &oeloc, &oelen, 0)) != -1) { |
1913 | udf_write_aext(inode, &epos, neloc, nelen, 1); | 1920 | udf_write_aext(inode, &epos, &neloc, nelen, 1); |
1914 | neloc = oeloc; | 1921 | neloc = oeloc; |
1915 | nelen = (etype << 30) | oelen; | 1922 | nelen = (etype << 30) | oelen; |
1916 | } | 1923 | } |
1917 | udf_add_aext(inode, &epos, neloc, nelen, 1); | 1924 | udf_add_aext(inode, &epos, &neloc, nelen, 1); |
1918 | brelse(epos.bh); | 1925 | brelse(epos.bh); |
1919 | 1926 | ||
1920 | return (nelen >> 30); | 1927 | return (nelen >> 30); |
1921 | } | 1928 | } |
1922 | 1929 | ||
1923 | int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | 1930 | int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, |
1924 | kernel_lb_addr eloc, uint32_t elen) | 1931 | struct kernel_lb_addr eloc, uint32_t elen) |
1925 | { | 1932 | { |
1926 | struct extent_position oepos; | 1933 | struct extent_position oepos; |
1927 | int adsize; | 1934 | int adsize; |
@@ -1936,9 +1943,9 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
1936 | 1943 | ||
1937 | iinfo = UDF_I(inode); | 1944 | iinfo = UDF_I(inode); |
1938 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 1945 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
1939 | adsize = sizeof(short_ad); | 1946 | adsize = sizeof(struct short_ad); |
1940 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 1947 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
1941 | adsize = sizeof(long_ad); | 1948 | adsize = sizeof(struct long_ad); |
1942 | else | 1949 | else |
1943 | adsize = 0; | 1950 | adsize = 0; |
1944 | 1951 | ||
@@ -1947,7 +1954,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
1947 | return -1; | 1954 | return -1; |
1948 | 1955 | ||
1949 | while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { | 1956 | while ((etype = udf_next_aext(inode, &epos, &eloc, &elen, 1)) != -1) { |
1950 | udf_write_aext(inode, &oepos, eloc, (etype << 30) | elen, 1); | 1957 | udf_write_aext(inode, &oepos, &eloc, (etype << 30) | elen, 1); |
1951 | if (oepos.bh != epos.bh) { | 1958 | if (oepos.bh != epos.bh) { |
1952 | oepos.block = epos.block; | 1959 | oepos.block = epos.block; |
1953 | brelse(oepos.bh); | 1960 | brelse(oepos.bh); |
@@ -1956,13 +1963,13 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
1956 | oepos.offset = epos.offset - adsize; | 1963 | oepos.offset = epos.offset - adsize; |
1957 | } | 1964 | } |
1958 | } | 1965 | } |
1959 | memset(&eloc, 0x00, sizeof(kernel_lb_addr)); | 1966 | memset(&eloc, 0x00, sizeof(struct kernel_lb_addr)); |
1960 | elen = 0; | 1967 | elen = 0; |
1961 | 1968 | ||
1962 | if (epos.bh != oepos.bh) { | 1969 | if (epos.bh != oepos.bh) { |
1963 | udf_free_blocks(inode->i_sb, inode, epos.block, 0, 1); | 1970 | udf_free_blocks(inode->i_sb, inode, &epos.block, 0, 1); |
1964 | udf_write_aext(inode, &oepos, eloc, elen, 1); | 1971 | udf_write_aext(inode, &oepos, &eloc, elen, 1); |
1965 | udf_write_aext(inode, &oepos, eloc, elen, 1); | 1972 | udf_write_aext(inode, &oepos, &eloc, elen, 1); |
1966 | if (!oepos.bh) { | 1973 | if (!oepos.bh) { |
1967 | iinfo->i_lenAlloc -= (adsize * 2); | 1974 | iinfo->i_lenAlloc -= (adsize * 2); |
1968 | mark_inode_dirty(inode); | 1975 | mark_inode_dirty(inode); |
@@ -1979,7 +1986,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
1979 | mark_buffer_dirty_inode(oepos.bh, inode); | 1986 | mark_buffer_dirty_inode(oepos.bh, inode); |
1980 | } | 1987 | } |
1981 | } else { | 1988 | } else { |
1982 | udf_write_aext(inode, &oepos, eloc, elen, 1); | 1989 | udf_write_aext(inode, &oepos, &eloc, elen, 1); |
1983 | if (!oepos.bh) { | 1990 | if (!oepos.bh) { |
1984 | iinfo->i_lenAlloc -= adsize; | 1991 | iinfo->i_lenAlloc -= adsize; |
1985 | mark_inode_dirty(inode); | 1992 | mark_inode_dirty(inode); |
@@ -2004,7 +2011,7 @@ int8_t udf_delete_aext(struct inode *inode, struct extent_position epos, | |||
2004 | } | 2011 | } |
2005 | 2012 | ||
2006 | int8_t inode_bmap(struct inode *inode, sector_t block, | 2013 | int8_t inode_bmap(struct inode *inode, sector_t block, |
2007 | struct extent_position *pos, kernel_lb_addr *eloc, | 2014 | struct extent_position *pos, struct kernel_lb_addr *eloc, |
2008 | uint32_t *elen, sector_t *offset) | 2015 | uint32_t *elen, sector_t *offset) |
2009 | { | 2016 | { |
2010 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; | 2017 | unsigned char blocksize_bits = inode->i_sb->s_blocksize_bits; |
@@ -2036,7 +2043,7 @@ int8_t inode_bmap(struct inode *inode, sector_t block, | |||
2036 | 2043 | ||
2037 | long udf_block_map(struct inode *inode, sector_t block) | 2044 | long udf_block_map(struct inode *inode, sector_t block) |
2038 | { | 2045 | { |
2039 | kernel_lb_addr eloc; | 2046 | struct kernel_lb_addr eloc; |
2040 | uint32_t elen; | 2047 | uint32_t elen; |
2041 | sector_t offset; | 2048 | sector_t offset; |
2042 | struct extent_position epos = {}; | 2049 | struct extent_position epos = {}; |
@@ -2046,7 +2053,7 @@ long udf_block_map(struct inode *inode, sector_t block) | |||
2046 | 2053 | ||
2047 | if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == | 2054 | if (inode_bmap(inode, block, &epos, &eloc, &elen, &offset) == |
2048 | (EXT_RECORDED_ALLOCATED >> 30)) | 2055 | (EXT_RECORDED_ALLOCATED >> 30)) |
2049 | ret = udf_get_lb_pblock(inode->i_sb, eloc, offset); | 2056 | ret = udf_get_lb_pblock(inode->i_sb, &eloc, offset); |
2050 | else | 2057 | else |
2051 | ret = 0; | 2058 | ret = 0; |
2052 | 2059 | ||
diff --git a/fs/udf/misc.c b/fs/udf/misc.c index 84bf0fd4a4f1..9215700c00a4 100644 --- a/fs/udf/misc.c +++ b/fs/udf/misc.c | |||
@@ -134,10 +134,10 @@ struct genericFormat *udf_add_extendedattr(struct inode *inode, uint32_t size, | |||
134 | } | 134 | } |
135 | } | 135 | } |
136 | /* rewrite CRC + checksum of eahd */ | 136 | /* rewrite CRC + checksum of eahd */ |
137 | crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(tag); | 137 | crclen = sizeof(struct extendedAttrHeaderDesc) - sizeof(struct tag); |
138 | eahd->descTag.descCRCLength = cpu_to_le16(crclen); | 138 | eahd->descTag.descCRCLength = cpu_to_le16(crclen); |
139 | eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd + | 139 | eahd->descTag.descCRC = cpu_to_le16(crc_itu_t(0, (char *)eahd + |
140 | sizeof(tag), crclen)); | 140 | sizeof(struct tag), crclen)); |
141 | eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); | 141 | eahd->descTag.tagChecksum = udf_tag_checksum(&eahd->descTag); |
142 | iinfo->i_lenEAttr += size; | 142 | iinfo->i_lenEAttr += size; |
143 | return (struct genericFormat *)&ea[offset]; | 143 | return (struct genericFormat *)&ea[offset]; |
@@ -202,7 +202,7 @@ struct genericFormat *udf_get_extendedattr(struct inode *inode, uint32_t type, | |||
202 | struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | 202 | struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, |
203 | uint32_t location, uint16_t *ident) | 203 | uint32_t location, uint16_t *ident) |
204 | { | 204 | { |
205 | tag *tag_p; | 205 | struct tag *tag_p; |
206 | struct buffer_head *bh = NULL; | 206 | struct buffer_head *bh = NULL; |
207 | 207 | ||
208 | /* Read the block */ | 208 | /* Read the block */ |
@@ -216,7 +216,7 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
216 | return NULL; | 216 | return NULL; |
217 | } | 217 | } |
218 | 218 | ||
219 | tag_p = (tag *)(bh->b_data); | 219 | tag_p = (struct tag *)(bh->b_data); |
220 | 220 | ||
221 | *ident = le16_to_cpu(tag_p->tagIdent); | 221 | *ident = le16_to_cpu(tag_p->tagIdent); |
222 | 222 | ||
@@ -241,9 +241,9 @@ struct buffer_head *udf_read_tagged(struct super_block *sb, uint32_t block, | |||
241 | } | 241 | } |
242 | 242 | ||
243 | /* Verify the descriptor CRC */ | 243 | /* Verify the descriptor CRC */ |
244 | if (le16_to_cpu(tag_p->descCRCLength) + sizeof(tag) > sb->s_blocksize || | 244 | if (le16_to_cpu(tag_p->descCRCLength) + sizeof(struct tag) > sb->s_blocksize || |
245 | le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, | 245 | le16_to_cpu(tag_p->descCRC) == crc_itu_t(0, |
246 | bh->b_data + sizeof(tag), | 246 | bh->b_data + sizeof(struct tag), |
247 | le16_to_cpu(tag_p->descCRCLength))) | 247 | le16_to_cpu(tag_p->descCRCLength))) |
248 | return bh; | 248 | return bh; |
249 | 249 | ||
@@ -255,27 +255,28 @@ error_out: | |||
255 | return NULL; | 255 | return NULL; |
256 | } | 256 | } |
257 | 257 | ||
258 | struct buffer_head *udf_read_ptagged(struct super_block *sb, kernel_lb_addr loc, | 258 | struct buffer_head *udf_read_ptagged(struct super_block *sb, |
259 | struct kernel_lb_addr *loc, | ||
259 | uint32_t offset, uint16_t *ident) | 260 | uint32_t offset, uint16_t *ident) |
260 | { | 261 | { |
261 | return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), | 262 | return udf_read_tagged(sb, udf_get_lb_pblock(sb, loc, offset), |
262 | loc.logicalBlockNum + offset, ident); | 263 | loc->logicalBlockNum + offset, ident); |
263 | } | 264 | } |
264 | 265 | ||
265 | void udf_update_tag(char *data, int length) | 266 | void udf_update_tag(char *data, int length) |
266 | { | 267 | { |
267 | tag *tptr = (tag *)data; | 268 | struct tag *tptr = (struct tag *)data; |
268 | length -= sizeof(tag); | 269 | length -= sizeof(struct tag); |
269 | 270 | ||
270 | tptr->descCRCLength = cpu_to_le16(length); | 271 | tptr->descCRCLength = cpu_to_le16(length); |
271 | tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(tag), length)); | 272 | tptr->descCRC = cpu_to_le16(crc_itu_t(0, data + sizeof(struct tag), length)); |
272 | tptr->tagChecksum = udf_tag_checksum(tptr); | 273 | tptr->tagChecksum = udf_tag_checksum(tptr); |
273 | } | 274 | } |
274 | 275 | ||
275 | void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, | 276 | void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, |
276 | uint32_t loc, int length) | 277 | uint32_t loc, int length) |
277 | { | 278 | { |
278 | tag *tptr = (tag *)data; | 279 | struct tag *tptr = (struct tag *)data; |
279 | tptr->tagIdent = cpu_to_le16(ident); | 280 | tptr->tagIdent = cpu_to_le16(ident); |
280 | tptr->descVersion = cpu_to_le16(version); | 281 | tptr->descVersion = cpu_to_le16(version); |
281 | tptr->tagSerialNum = cpu_to_le16(snum); | 282 | tptr->tagSerialNum = cpu_to_le16(snum); |
@@ -283,12 +284,12 @@ void udf_new_tag(char *data, uint16_t ident, uint16_t version, uint16_t snum, | |||
283 | udf_update_tag(data, length); | 284 | udf_update_tag(data, length); |
284 | } | 285 | } |
285 | 286 | ||
286 | u8 udf_tag_checksum(const tag *t) | 287 | u8 udf_tag_checksum(const struct tag *t) |
287 | { | 288 | { |
288 | u8 *data = (u8 *)t; | 289 | u8 *data = (u8 *)t; |
289 | u8 checksum = 0; | 290 | u8 checksum = 0; |
290 | int i; | 291 | int i; |
291 | for (i = 0; i < sizeof(tag); ++i) | 292 | for (i = 0; i < sizeof(struct tag); ++i) |
292 | if (i != 4) /* position of checksum */ | 293 | if (i != 4) /* position of checksum */ |
293 | checksum += data[i]; | 294 | checksum += data[i]; |
294 | return checksum; | 295 | return checksum; |
diff --git a/fs/udf/namei.c b/fs/udf/namei.c index f84bfaa8d941..6a29fa34c478 100644 --- a/fs/udf/namei.c +++ b/fs/udf/namei.c | |||
@@ -47,7 +47,7 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, | |||
47 | struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh, | 47 | struct fileIdentDesc *sfi, struct udf_fileident_bh *fibh, |
48 | uint8_t *impuse, uint8_t *fileident) | 48 | uint8_t *impuse, uint8_t *fileident) |
49 | { | 49 | { |
50 | uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(tag); | 50 | uint16_t crclen = fibh->eoffset - fibh->soffset - sizeof(struct tag); |
51 | uint16_t crc; | 51 | uint16_t crc; |
52 | int offset; | 52 | int offset; |
53 | uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse); | 53 | uint16_t liu = le16_to_cpu(cfi->lengthOfImpUse); |
@@ -99,18 +99,18 @@ int udf_write_fi(struct inode *inode, struct fileIdentDesc *cfi, | |||
99 | memset(fibh->ebh->b_data, 0x00, padlen + offset); | 99 | memset(fibh->ebh->b_data, 0x00, padlen + offset); |
100 | } | 100 | } |
101 | 101 | ||
102 | crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(tag), | 102 | crc = crc_itu_t(0, (uint8_t *)cfi + sizeof(struct tag), |
103 | sizeof(struct fileIdentDesc) - sizeof(tag)); | 103 | sizeof(struct fileIdentDesc) - sizeof(struct tag)); |
104 | 104 | ||
105 | if (fibh->sbh == fibh->ebh) { | 105 | if (fibh->sbh == fibh->ebh) { |
106 | crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, | 106 | crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, |
107 | crclen + sizeof(tag) - | 107 | crclen + sizeof(struct tag) - |
108 | sizeof(struct fileIdentDesc)); | 108 | sizeof(struct fileIdentDesc)); |
109 | } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { | 109 | } else if (sizeof(struct fileIdentDesc) >= -fibh->soffset) { |
110 | crc = crc_itu_t(crc, fibh->ebh->b_data + | 110 | crc = crc_itu_t(crc, fibh->ebh->b_data + |
111 | sizeof(struct fileIdentDesc) + | 111 | sizeof(struct fileIdentDesc) + |
112 | fibh->soffset, | 112 | fibh->soffset, |
113 | crclen + sizeof(tag) - | 113 | crclen + sizeof(struct tag) - |
114 | sizeof(struct fileIdentDesc)); | 114 | sizeof(struct fileIdentDesc)); |
115 | } else { | 115 | } else { |
116 | crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, | 116 | crc = crc_itu_t(crc, (uint8_t *)sfi->impUse, |
@@ -154,7 +154,7 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
154 | uint8_t lfi; | 154 | uint8_t lfi; |
155 | uint16_t liu; | 155 | uint16_t liu; |
156 | loff_t size; | 156 | loff_t size; |
157 | kernel_lb_addr eloc; | 157 | struct kernel_lb_addr eloc; |
158 | uint32_t elen; | 158 | uint32_t elen; |
159 | sector_t offset; | 159 | sector_t offset; |
160 | struct extent_position epos = {}; | 160 | struct extent_position epos = {}; |
@@ -171,12 +171,12 @@ static struct fileIdentDesc *udf_find_entry(struct inode *dir, | |||
171 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, | 171 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, |
172 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) | 172 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) |
173 | goto out_err; | 173 | goto out_err; |
174 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 174 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); |
175 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 175 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
176 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 176 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
177 | epos.offset -= sizeof(short_ad); | 177 | epos.offset -= sizeof(struct short_ad); |
178 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 178 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
179 | epos.offset -= sizeof(long_ad); | 179 | epos.offset -= sizeof(struct long_ad); |
180 | } else | 180 | } else |
181 | offset = 0; | 181 | offset = 0; |
182 | 182 | ||
@@ -268,7 +268,7 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, | |||
268 | #ifdef UDF_RECOVERY | 268 | #ifdef UDF_RECOVERY |
269 | /* temporary shorthand for specifying files by inode number */ | 269 | /* temporary shorthand for specifying files by inode number */ |
270 | if (!strncmp(dentry->d_name.name, ".B=", 3)) { | 270 | if (!strncmp(dentry->d_name.name, ".B=", 3)) { |
271 | kernel_lb_addr lb = { | 271 | struct kernel_lb_addr lb = { |
272 | .logicalBlockNum = 0, | 272 | .logicalBlockNum = 0, |
273 | .partitionReferenceNum = | 273 | .partitionReferenceNum = |
274 | simple_strtoul(dentry->d_name.name + 3, | 274 | simple_strtoul(dentry->d_name.name + 3, |
@@ -283,11 +283,14 @@ static struct dentry *udf_lookup(struct inode *dir, struct dentry *dentry, | |||
283 | #endif /* UDF_RECOVERY */ | 283 | #endif /* UDF_RECOVERY */ |
284 | 284 | ||
285 | if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) { | 285 | if (udf_find_entry(dir, &dentry->d_name, &fibh, &cfi)) { |
286 | struct kernel_lb_addr loc; | ||
287 | |||
286 | if (fibh.sbh != fibh.ebh) | 288 | if (fibh.sbh != fibh.ebh) |
287 | brelse(fibh.ebh); | 289 | brelse(fibh.ebh); |
288 | brelse(fibh.sbh); | 290 | brelse(fibh.sbh); |
289 | 291 | ||
290 | inode = udf_iget(dir->i_sb, lelb_to_cpu(cfi.icb.extLocation)); | 292 | loc = lelb_to_cpu(cfi.icb.extLocation); |
293 | inode = udf_iget(dir->i_sb, &loc); | ||
291 | if (!inode) { | 294 | if (!inode) { |
292 | unlock_kernel(); | 295 | unlock_kernel(); |
293 | return ERR_PTR(-EACCES); | 296 | return ERR_PTR(-EACCES); |
@@ -313,7 +316,7 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
313 | uint8_t lfi; | 316 | uint8_t lfi; |
314 | uint16_t liu; | 317 | uint16_t liu; |
315 | int block; | 318 | int block; |
316 | kernel_lb_addr eloc; | 319 | struct kernel_lb_addr eloc; |
317 | uint32_t elen = 0; | 320 | uint32_t elen = 0; |
318 | sector_t offset; | 321 | sector_t offset; |
319 | struct extent_position epos = {}; | 322 | struct extent_position epos = {}; |
@@ -351,16 +354,16 @@ static struct fileIdentDesc *udf_add_entry(struct inode *dir, | |||
351 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, | 354 | if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, &epos, |
352 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) { | 355 | &eloc, &elen, &offset) != (EXT_RECORDED_ALLOCATED >> 30)) { |
353 | block = udf_get_lb_pblock(dir->i_sb, | 356 | block = udf_get_lb_pblock(dir->i_sb, |
354 | dinfo->i_location, 0); | 357 | &dinfo->i_location, 0); |
355 | fibh->soffset = fibh->eoffset = sb->s_blocksize; | 358 | fibh->soffset = fibh->eoffset = sb->s_blocksize; |
356 | goto add; | 359 | goto add; |
357 | } | 360 | } |
358 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 361 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); |
359 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 362 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
360 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 363 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
361 | epos.offset -= sizeof(short_ad); | 364 | epos.offset -= sizeof(struct short_ad); |
362 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 365 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
363 | epos.offset -= sizeof(long_ad); | 366 | epos.offset -= sizeof(struct long_ad); |
364 | } else | 367 | } else |
365 | offset = 0; | 368 | offset = 0; |
366 | 369 | ||
@@ -409,10 +412,10 @@ add: | |||
409 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) { | 412 | if (dinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB && elen) { |
410 | elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); | 413 | elen = (elen + sb->s_blocksize - 1) & ~(sb->s_blocksize - 1); |
411 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 414 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
412 | epos.offset -= sizeof(short_ad); | 415 | epos.offset -= sizeof(struct short_ad); |
413 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 416 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
414 | epos.offset -= sizeof(long_ad); | 417 | epos.offset -= sizeof(struct long_ad); |
415 | udf_write_aext(dir, &epos, eloc, elen, 1); | 418 | udf_write_aext(dir, &epos, &eloc, elen, 1); |
416 | } | 419 | } |
417 | f_pos += nfidlen; | 420 | f_pos += nfidlen; |
418 | 421 | ||
@@ -494,10 +497,10 @@ add: | |||
494 | memset(cfi, 0, sizeof(struct fileIdentDesc)); | 497 | memset(cfi, 0, sizeof(struct fileIdentDesc)); |
495 | if (UDF_SB(sb)->s_udfrev >= 0x0200) | 498 | if (UDF_SB(sb)->s_udfrev >= 0x0200) |
496 | udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, | 499 | udf_new_tag((char *)cfi, TAG_IDENT_FID, 3, 1, block, |
497 | sizeof(tag)); | 500 | sizeof(struct tag)); |
498 | else | 501 | else |
499 | udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, | 502 | udf_new_tag((char *)cfi, TAG_IDENT_FID, 2, 1, block, |
500 | sizeof(tag)); | 503 | sizeof(struct tag)); |
501 | cfi->fileVersionNum = cpu_to_le16(1); | 504 | cfi->fileVersionNum = cpu_to_le16(1); |
502 | cfi->lengthFileIdent = namelen; | 505 | cfi->lengthFileIdent = namelen; |
503 | cfi->lengthOfImpUse = cpu_to_le16(0); | 506 | cfi->lengthOfImpUse = cpu_to_le16(0); |
@@ -530,7 +533,7 @@ static int udf_delete_entry(struct inode *inode, struct fileIdentDesc *fi, | |||
530 | cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED; | 533 | cfi->fileCharacteristics |= FID_FILE_CHAR_DELETED; |
531 | 534 | ||
532 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) | 535 | if (UDF_QUERY_FLAG(inode->i_sb, UDF_FLAG_STRICT)) |
533 | memset(&(cfi->icb), 0x00, sizeof(long_ad)); | 536 | memset(&(cfi->icb), 0x00, sizeof(struct long_ad)); |
534 | 537 | ||
535 | return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); | 538 | return udf_write_fi(inode, cfi, fi, fibh, NULL, NULL); |
536 | } | 539 | } |
@@ -710,7 +713,7 @@ static int empty_dir(struct inode *dir) | |||
710 | loff_t f_pos; | 713 | loff_t f_pos; |
711 | loff_t size = udf_ext0_offset(dir) + dir->i_size; | 714 | loff_t size = udf_ext0_offset(dir) + dir->i_size; |
712 | int block; | 715 | int block; |
713 | kernel_lb_addr eloc; | 716 | struct kernel_lb_addr eloc; |
714 | uint32_t elen; | 717 | uint32_t elen; |
715 | sector_t offset; | 718 | sector_t offset; |
716 | struct extent_position epos = {}; | 719 | struct extent_position epos = {}; |
@@ -724,12 +727,12 @@ static int empty_dir(struct inode *dir) | |||
724 | else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, | 727 | else if (inode_bmap(dir, f_pos >> dir->i_sb->s_blocksize_bits, |
725 | &epos, &eloc, &elen, &offset) == | 728 | &epos, &eloc, &elen, &offset) == |
726 | (EXT_RECORDED_ALLOCATED >> 30)) { | 729 | (EXT_RECORDED_ALLOCATED >> 30)) { |
727 | block = udf_get_lb_pblock(dir->i_sb, eloc, offset); | 730 | block = udf_get_lb_pblock(dir->i_sb, &eloc, offset); |
728 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { | 731 | if ((++offset << dir->i_sb->s_blocksize_bits) < elen) { |
729 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 732 | if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
730 | epos.offset -= sizeof(short_ad); | 733 | epos.offset -= sizeof(struct short_ad); |
731 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 734 | else if (dinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
732 | epos.offset -= sizeof(long_ad); | 735 | epos.offset -= sizeof(struct long_ad); |
733 | } else | 736 | } else |
734 | offset = 0; | 737 | offset = 0; |
735 | 738 | ||
@@ -778,7 +781,7 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) | |||
778 | struct inode *inode = dentry->d_inode; | 781 | struct inode *inode = dentry->d_inode; |
779 | struct udf_fileident_bh fibh; | 782 | struct udf_fileident_bh fibh; |
780 | struct fileIdentDesc *fi, cfi; | 783 | struct fileIdentDesc *fi, cfi; |
781 | kernel_lb_addr tloc; | 784 | struct kernel_lb_addr tloc; |
782 | 785 | ||
783 | retval = -ENOENT; | 786 | retval = -ENOENT; |
784 | lock_kernel(); | 787 | lock_kernel(); |
@@ -788,7 +791,7 @@ static int udf_rmdir(struct inode *dir, struct dentry *dentry) | |||
788 | 791 | ||
789 | retval = -EIO; | 792 | retval = -EIO; |
790 | tloc = lelb_to_cpu(cfi.icb.extLocation); | 793 | tloc = lelb_to_cpu(cfi.icb.extLocation); |
791 | if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino) | 794 | if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino) |
792 | goto end_rmdir; | 795 | goto end_rmdir; |
793 | retval = -ENOTEMPTY; | 796 | retval = -ENOTEMPTY; |
794 | if (!empty_dir(inode)) | 797 | if (!empty_dir(inode)) |
@@ -824,7 +827,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) | |||
824 | struct udf_fileident_bh fibh; | 827 | struct udf_fileident_bh fibh; |
825 | struct fileIdentDesc *fi; | 828 | struct fileIdentDesc *fi; |
826 | struct fileIdentDesc cfi; | 829 | struct fileIdentDesc cfi; |
827 | kernel_lb_addr tloc; | 830 | struct kernel_lb_addr tloc; |
828 | 831 | ||
829 | retval = -ENOENT; | 832 | retval = -ENOENT; |
830 | lock_kernel(); | 833 | lock_kernel(); |
@@ -834,7 +837,7 @@ static int udf_unlink(struct inode *dir, struct dentry *dentry) | |||
834 | 837 | ||
835 | retval = -EIO; | 838 | retval = -EIO; |
836 | tloc = lelb_to_cpu(cfi.icb.extLocation); | 839 | tloc = lelb_to_cpu(cfi.icb.extLocation); |
837 | if (udf_get_lb_pblock(dir->i_sb, tloc, 0) != inode->i_ino) | 840 | if (udf_get_lb_pblock(dir->i_sb, &tloc, 0) != inode->i_ino) |
838 | goto end_unlink; | 841 | goto end_unlink; |
839 | 842 | ||
840 | if (!inode->i_nlink) { | 843 | if (!inode->i_nlink) { |
@@ -897,7 +900,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
897 | inode->i_op = &page_symlink_inode_operations; | 900 | inode->i_op = &page_symlink_inode_operations; |
898 | 901 | ||
899 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { | 902 | if (iinfo->i_alloc_type != ICBTAG_FLAG_AD_IN_ICB) { |
900 | kernel_lb_addr eloc; | 903 | struct kernel_lb_addr eloc; |
901 | uint32_t bsize; | 904 | uint32_t bsize; |
902 | 905 | ||
903 | block = udf_new_block(inode->i_sb, inode, | 906 | block = udf_new_block(inode->i_sb, inode, |
@@ -913,7 +916,7 @@ static int udf_symlink(struct inode *dir, struct dentry *dentry, | |||
913 | iinfo->i_location.partitionReferenceNum; | 916 | iinfo->i_location.partitionReferenceNum; |
914 | bsize = inode->i_sb->s_blocksize; | 917 | bsize = inode->i_sb->s_blocksize; |
915 | iinfo->i_lenExtents = bsize; | 918 | iinfo->i_lenExtents = bsize; |
916 | udf_add_aext(inode, &epos, eloc, bsize, 0); | 919 | udf_add_aext(inode, &epos, &eloc, bsize, 0); |
917 | brelse(epos.bh); | 920 | brelse(epos.bh); |
918 | 921 | ||
919 | block = udf_get_pblock(inode->i_sb, block, | 922 | block = udf_get_pblock(inode->i_sb, block, |
@@ -1108,7 +1111,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1108 | struct fileIdentDesc ocfi, ncfi; | 1111 | struct fileIdentDesc ocfi, ncfi; |
1109 | struct buffer_head *dir_bh = NULL; | 1112 | struct buffer_head *dir_bh = NULL; |
1110 | int retval = -ENOENT; | 1113 | int retval = -ENOENT; |
1111 | kernel_lb_addr tloc; | 1114 | struct kernel_lb_addr tloc; |
1112 | struct udf_inode_info *old_iinfo = UDF_I(old_inode); | 1115 | struct udf_inode_info *old_iinfo = UDF_I(old_inode); |
1113 | 1116 | ||
1114 | lock_kernel(); | 1117 | lock_kernel(); |
@@ -1119,7 +1122,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1119 | brelse(ofibh.sbh); | 1122 | brelse(ofibh.sbh); |
1120 | } | 1123 | } |
1121 | tloc = lelb_to_cpu(ocfi.icb.extLocation); | 1124 | tloc = lelb_to_cpu(ocfi.icb.extLocation); |
1122 | if (!ofi || udf_get_lb_pblock(old_dir->i_sb, tloc, 0) | 1125 | if (!ofi || udf_get_lb_pblock(old_dir->i_sb, &tloc, 0) |
1123 | != old_inode->i_ino) | 1126 | != old_inode->i_ino) |
1124 | goto end_rename; | 1127 | goto end_rename; |
1125 | 1128 | ||
@@ -1158,7 +1161,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1158 | if (!dir_fi) | 1161 | if (!dir_fi) |
1159 | goto end_rename; | 1162 | goto end_rename; |
1160 | tloc = lelb_to_cpu(dir_fi->icb.extLocation); | 1163 | tloc = lelb_to_cpu(dir_fi->icb.extLocation); |
1161 | if (udf_get_lb_pblock(old_inode->i_sb, tloc, 0) != | 1164 | if (udf_get_lb_pblock(old_inode->i_sb, &tloc, 0) != |
1162 | old_dir->i_ino) | 1165 | old_dir->i_ino) |
1163 | goto end_rename; | 1166 | goto end_rename; |
1164 | 1167 | ||
@@ -1187,7 +1190,7 @@ static int udf_rename(struct inode *old_dir, struct dentry *old_dentry, | |||
1187 | */ | 1190 | */ |
1188 | ncfi.fileVersionNum = ocfi.fileVersionNum; | 1191 | ncfi.fileVersionNum = ocfi.fileVersionNum; |
1189 | ncfi.fileCharacteristics = ocfi.fileCharacteristics; | 1192 | ncfi.fileCharacteristics = ocfi.fileCharacteristics; |
1190 | memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(long_ad)); | 1193 | memcpy(&(ncfi.icb), &(ocfi.icb), sizeof(struct long_ad)); |
1191 | udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL); | 1194 | udf_write_fi(new_dir, &ncfi, nfi, &nfibh, NULL, NULL); |
1192 | 1195 | ||
1193 | /* The old fid may have moved - find it again */ | 1196 | /* The old fid may have moved - find it again */ |
@@ -1242,6 +1245,7 @@ end_rename: | |||
1242 | 1245 | ||
1243 | static struct dentry *udf_get_parent(struct dentry *child) | 1246 | static struct dentry *udf_get_parent(struct dentry *child) |
1244 | { | 1247 | { |
1248 | struct kernel_lb_addr tloc; | ||
1245 | struct inode *inode = NULL; | 1249 | struct inode *inode = NULL; |
1246 | struct qstr dotdot = {.name = "..", .len = 2}; | 1250 | struct qstr dotdot = {.name = "..", .len = 2}; |
1247 | struct fileIdentDesc cfi; | 1251 | struct fileIdentDesc cfi; |
@@ -1255,8 +1259,8 @@ static struct dentry *udf_get_parent(struct dentry *child) | |||
1255 | brelse(fibh.ebh); | 1259 | brelse(fibh.ebh); |
1256 | brelse(fibh.sbh); | 1260 | brelse(fibh.sbh); |
1257 | 1261 | ||
1258 | inode = udf_iget(child->d_inode->i_sb, | 1262 | tloc = lelb_to_cpu(cfi.icb.extLocation); |
1259 | lelb_to_cpu(cfi.icb.extLocation)); | 1263 | inode = udf_iget(child->d_inode->i_sb, &tloc); |
1260 | if (!inode) | 1264 | if (!inode) |
1261 | goto out_unlock; | 1265 | goto out_unlock; |
1262 | unlock_kernel(); | 1266 | unlock_kernel(); |
@@ -1272,14 +1276,14 @@ static struct dentry *udf_nfs_get_inode(struct super_block *sb, u32 block, | |||
1272 | u16 partref, __u32 generation) | 1276 | u16 partref, __u32 generation) |
1273 | { | 1277 | { |
1274 | struct inode *inode; | 1278 | struct inode *inode; |
1275 | kernel_lb_addr loc; | 1279 | struct kernel_lb_addr loc; |
1276 | 1280 | ||
1277 | if (block == 0) | 1281 | if (block == 0) |
1278 | return ERR_PTR(-ESTALE); | 1282 | return ERR_PTR(-ESTALE); |
1279 | 1283 | ||
1280 | loc.logicalBlockNum = block; | 1284 | loc.logicalBlockNum = block; |
1281 | loc.partitionReferenceNum = partref; | 1285 | loc.partitionReferenceNum = partref; |
1282 | inode = udf_iget(sb, loc); | 1286 | inode = udf_iget(sb, &loc); |
1283 | 1287 | ||
1284 | if (inode == NULL) | 1288 | if (inode == NULL) |
1285 | return ERR_PTR(-ENOMEM); | 1289 | return ERR_PTR(-ENOMEM); |
@@ -1318,7 +1322,7 @@ static int udf_encode_fh(struct dentry *de, __u32 *fh, int *lenp, | |||
1318 | { | 1322 | { |
1319 | int len = *lenp; | 1323 | int len = *lenp; |
1320 | struct inode *inode = de->d_inode; | 1324 | struct inode *inode = de->d_inode; |
1321 | kernel_lb_addr location = UDF_I(inode)->i_location; | 1325 | struct kernel_lb_addr location = UDF_I(inode)->i_location; |
1322 | struct fid *fid = (struct fid *)fh; | 1326 | struct fid *fid = (struct fid *)fh; |
1323 | int type = FILEID_UDF_WITHOUT_PARENT; | 1327 | int type = FILEID_UDF_WITHOUT_PARENT; |
1324 | 1328 | ||
diff --git a/fs/udf/osta_udf.h b/fs/udf/osta_udf.h index 65ff47902bd2..fbff74654df2 100644 --- a/fs/udf/osta_udf.h +++ b/fs/udf/osta_udf.h | |||
@@ -85,7 +85,7 @@ struct appIdentSuffix { | |||
85 | /* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */ | 85 | /* Logical Volume Integrity Descriptor (UDF 2.50 2.2.6) */ |
86 | /* Implementation Use (UDF 2.50 2.2.6.4) */ | 86 | /* Implementation Use (UDF 2.50 2.2.6.4) */ |
87 | struct logicalVolIntegrityDescImpUse { | 87 | struct logicalVolIntegrityDescImpUse { |
88 | regid impIdent; | 88 | struct regid impIdent; |
89 | __le32 numFiles; | 89 | __le32 numFiles; |
90 | __le32 numDirs; | 90 | __le32 numDirs; |
91 | __le16 minUDFReadRev; | 91 | __le16 minUDFReadRev; |
@@ -97,12 +97,12 @@ struct logicalVolIntegrityDescImpUse { | |||
97 | /* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */ | 97 | /* Implementation Use Volume Descriptor (UDF 2.50 2.2.7) */ |
98 | /* Implementation Use (UDF 2.50 2.2.7.2) */ | 98 | /* Implementation Use (UDF 2.50 2.2.7.2) */ |
99 | struct impUseVolDescImpUse { | 99 | struct impUseVolDescImpUse { |
100 | charspec LVICharset; | 100 | struct charspec LVICharset; |
101 | dstring logicalVolIdent[128]; | 101 | dstring logicalVolIdent[128]; |
102 | dstring LVInfo1[36]; | 102 | dstring LVInfo1[36]; |
103 | dstring LVInfo2[36]; | 103 | dstring LVInfo2[36]; |
104 | dstring LVInfo3[36]; | 104 | dstring LVInfo3[36]; |
105 | regid impIdent; | 105 | struct regid impIdent; |
106 | uint8_t impUse[128]; | 106 | uint8_t impUse[128]; |
107 | } __attribute__ ((packed)); | 107 | } __attribute__ ((packed)); |
108 | 108 | ||
@@ -110,7 +110,7 @@ struct udfPartitionMap2 { | |||
110 | uint8_t partitionMapType; | 110 | uint8_t partitionMapType; |
111 | uint8_t partitionMapLength; | 111 | uint8_t partitionMapLength; |
112 | uint8_t reserved1[2]; | 112 | uint8_t reserved1[2]; |
113 | regid partIdent; | 113 | struct regid partIdent; |
114 | __le16 volSeqNum; | 114 | __le16 volSeqNum; |
115 | __le16 partitionNum; | 115 | __le16 partitionNum; |
116 | } __attribute__ ((packed)); | 116 | } __attribute__ ((packed)); |
@@ -120,7 +120,7 @@ struct virtualPartitionMap { | |||
120 | uint8_t partitionMapType; | 120 | uint8_t partitionMapType; |
121 | uint8_t partitionMapLength; | 121 | uint8_t partitionMapLength; |
122 | uint8_t reserved1[2]; | 122 | uint8_t reserved1[2]; |
123 | regid partIdent; | 123 | struct regid partIdent; |
124 | __le16 volSeqNum; | 124 | __le16 volSeqNum; |
125 | __le16 partitionNum; | 125 | __le16 partitionNum; |
126 | uint8_t reserved2[24]; | 126 | uint8_t reserved2[24]; |
@@ -131,7 +131,7 @@ struct sparablePartitionMap { | |||
131 | uint8_t partitionMapType; | 131 | uint8_t partitionMapType; |
132 | uint8_t partitionMapLength; | 132 | uint8_t partitionMapLength; |
133 | uint8_t reserved1[2]; | 133 | uint8_t reserved1[2]; |
134 | regid partIdent; | 134 | struct regid partIdent; |
135 | __le16 volSeqNum; | 135 | __le16 volSeqNum; |
136 | __le16 partitionNum; | 136 | __le16 partitionNum; |
137 | __le16 packetLength; | 137 | __le16 packetLength; |
@@ -146,7 +146,7 @@ struct metadataPartitionMap { | |||
146 | uint8_t partitionMapType; | 146 | uint8_t partitionMapType; |
147 | uint8_t partitionMapLength; | 147 | uint8_t partitionMapLength; |
148 | uint8_t reserved1[2]; | 148 | uint8_t reserved1[2]; |
149 | regid partIdent; | 149 | struct regid partIdent; |
150 | __le16 volSeqNum; | 150 | __le16 volSeqNum; |
151 | __le16 partitionNum; | 151 | __le16 partitionNum; |
152 | __le32 metadataFileLoc; | 152 | __le32 metadataFileLoc; |
@@ -161,7 +161,7 @@ struct metadataPartitionMap { | |||
161 | /* Virtual Allocation Table (UDF 1.5 2.2.10) */ | 161 | /* Virtual Allocation Table (UDF 1.5 2.2.10) */ |
162 | struct virtualAllocationTable15 { | 162 | struct virtualAllocationTable15 { |
163 | __le32 VirtualSector[0]; | 163 | __le32 VirtualSector[0]; |
164 | regid vatIdent; | 164 | struct regid vatIdent; |
165 | __le32 previousVATICBLoc; | 165 | __le32 previousVATICBLoc; |
166 | } __attribute__ ((packed)); | 166 | } __attribute__ ((packed)); |
167 | 167 | ||
@@ -192,8 +192,8 @@ struct sparingEntry { | |||
192 | } __attribute__ ((packed)); | 192 | } __attribute__ ((packed)); |
193 | 193 | ||
194 | struct sparingTable { | 194 | struct sparingTable { |
195 | tag descTag; | 195 | struct tag descTag; |
196 | regid sparingIdent; | 196 | struct regid sparingIdent; |
197 | __le16 reallocationTableLen; | 197 | __le16 reallocationTableLen; |
198 | __le16 reserved; | 198 | __le16 reserved; |
199 | __le32 sequenceNum; | 199 | __le32 sequenceNum; |
@@ -206,7 +206,7 @@ struct sparingTable { | |||
206 | #define ICBTAG_FILE_TYPE_MIRROR 0xFB | 206 | #define ICBTAG_FILE_TYPE_MIRROR 0xFB |
207 | #define ICBTAG_FILE_TYPE_BITMAP 0xFC | 207 | #define ICBTAG_FILE_TYPE_BITMAP 0xFC |
208 | 208 | ||
209 | /* struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */ | 209 | /* struct struct long_ad ICB - ADImpUse (UDF 2.50 2.2.4.3) */ |
210 | struct allocDescImpUse { | 210 | struct allocDescImpUse { |
211 | __le16 flags; | 211 | __le16 flags; |
212 | uint8_t impUse[4]; | 212 | uint8_t impUse[4]; |
diff --git a/fs/udf/partition.c b/fs/udf/partition.c index 96dfd207c3d6..4b540ee632d5 100644 --- a/fs/udf/partition.c +++ b/fs/udf/partition.c | |||
@@ -273,7 +273,7 @@ static uint32_t udf_try_read_meta(struct inode *inode, uint32_t block, | |||
273 | { | 273 | { |
274 | struct super_block *sb = inode->i_sb; | 274 | struct super_block *sb = inode->i_sb; |
275 | struct udf_part_map *map; | 275 | struct udf_part_map *map; |
276 | kernel_lb_addr eloc; | 276 | struct kernel_lb_addr eloc; |
277 | uint32_t elen; | 277 | uint32_t elen; |
278 | sector_t ext_offset; | 278 | sector_t ext_offset; |
279 | struct extent_position epos = {}; | 279 | struct extent_position epos = {}; |
diff --git a/fs/udf/super.c b/fs/udf/super.c index e25e7010627b..72348cc855a4 100644 --- a/fs/udf/super.c +++ b/fs/udf/super.c | |||
@@ -81,16 +81,13 @@ static char error_buf[1024]; | |||
81 | /* These are the "meat" - everything else is stuffing */ | 81 | /* These are the "meat" - everything else is stuffing */ |
82 | static int udf_fill_super(struct super_block *, void *, int); | 82 | static int udf_fill_super(struct super_block *, void *, int); |
83 | static void udf_put_super(struct super_block *); | 83 | static void udf_put_super(struct super_block *); |
84 | static void udf_write_super(struct super_block *); | 84 | static int udf_sync_fs(struct super_block *, int); |
85 | static int udf_remount_fs(struct super_block *, int *, char *); | 85 | static int udf_remount_fs(struct super_block *, int *, char *); |
86 | static int udf_check_valid(struct super_block *, int, int); | 86 | static void udf_load_logicalvolint(struct super_block *, struct kernel_extent_ad); |
87 | static int udf_vrs(struct super_block *sb, int silent); | 87 | static int udf_find_fileset(struct super_block *, struct kernel_lb_addr *, |
88 | static void udf_load_logicalvolint(struct super_block *, kernel_extent_ad); | 88 | struct kernel_lb_addr *); |
89 | static void udf_find_anchor(struct super_block *); | ||
90 | static int udf_find_fileset(struct super_block *, kernel_lb_addr *, | ||
91 | kernel_lb_addr *); | ||
92 | static void udf_load_fileset(struct super_block *, struct buffer_head *, | 89 | static void udf_load_fileset(struct super_block *, struct buffer_head *, |
93 | kernel_lb_addr *); | 90 | struct kernel_lb_addr *); |
94 | static void udf_open_lvid(struct super_block *); | 91 | static void udf_open_lvid(struct super_block *); |
95 | static void udf_close_lvid(struct super_block *); | 92 | static void udf_close_lvid(struct super_block *); |
96 | static unsigned int udf_count_free(struct super_block *); | 93 | static unsigned int udf_count_free(struct super_block *); |
@@ -181,7 +178,7 @@ static const struct super_operations udf_sb_ops = { | |||
181 | .delete_inode = udf_delete_inode, | 178 | .delete_inode = udf_delete_inode, |
182 | .clear_inode = udf_clear_inode, | 179 | .clear_inode = udf_clear_inode, |
183 | .put_super = udf_put_super, | 180 | .put_super = udf_put_super, |
184 | .write_super = udf_write_super, | 181 | .sync_fs = udf_sync_fs, |
185 | .statfs = udf_statfs, | 182 | .statfs = udf_statfs, |
186 | .remount_fs = udf_remount_fs, | 183 | .remount_fs = udf_remount_fs, |
187 | .show_options = udf_show_options, | 184 | .show_options = udf_show_options, |
@@ -201,6 +198,8 @@ struct udf_options { | |||
201 | mode_t umask; | 198 | mode_t umask; |
202 | gid_t gid; | 199 | gid_t gid; |
203 | uid_t uid; | 200 | uid_t uid; |
201 | mode_t fmode; | ||
202 | mode_t dmode; | ||
204 | struct nls_table *nls_map; | 203 | struct nls_table *nls_map; |
205 | }; | 204 | }; |
206 | 205 | ||
@@ -258,7 +257,7 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) | |||
258 | 257 | ||
259 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) | 258 | if (!UDF_QUERY_FLAG(sb, UDF_FLAG_STRICT)) |
260 | seq_puts(seq, ",nostrict"); | 259 | seq_puts(seq, ",nostrict"); |
261 | if (sb->s_blocksize != UDF_DEFAULT_BLOCKSIZE) | 260 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_BLOCKSIZE_SET)) |
262 | seq_printf(seq, ",bs=%lu", sb->s_blocksize); | 261 | seq_printf(seq, ",bs=%lu", sb->s_blocksize); |
263 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) | 262 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UNHIDE)) |
264 | seq_puts(seq, ",unhide"); | 263 | seq_puts(seq, ",unhide"); |
@@ -282,18 +281,16 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) | |||
282 | seq_printf(seq, ",gid=%u", sbi->s_gid); | 281 | seq_printf(seq, ",gid=%u", sbi->s_gid); |
283 | if (sbi->s_umask != 0) | 282 | if (sbi->s_umask != 0) |
284 | seq_printf(seq, ",umask=%o", sbi->s_umask); | 283 | seq_printf(seq, ",umask=%o", sbi->s_umask); |
284 | if (sbi->s_fmode != UDF_INVALID_MODE) | ||
285 | seq_printf(seq, ",mode=%o", sbi->s_fmode); | ||
286 | if (sbi->s_dmode != UDF_INVALID_MODE) | ||
287 | seq_printf(seq, ",dmode=%o", sbi->s_dmode); | ||
285 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET)) | 288 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_SESSION_SET)) |
286 | seq_printf(seq, ",session=%u", sbi->s_session); | 289 | seq_printf(seq, ",session=%u", sbi->s_session); |
287 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET)) | 290 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_LASTBLOCK_SET)) |
288 | seq_printf(seq, ",lastblock=%u", sbi->s_last_block); | 291 | seq_printf(seq, ",lastblock=%u", sbi->s_last_block); |
289 | /* | 292 | if (sbi->s_anchor != 0) |
290 | * s_anchor[2] could be zeroed out in case there is no anchor | 293 | seq_printf(seq, ",anchor=%u", sbi->s_anchor); |
291 | * in the specified block, but then the "anchor=N" option | ||
292 | * originally given by the user wasn't effective, so it's OK | ||
293 | * if we don't show it. | ||
294 | */ | ||
295 | if (sbi->s_anchor[2] != 0) | ||
296 | seq_printf(seq, ",anchor=%u", sbi->s_anchor[2]); | ||
297 | /* | 294 | /* |
298 | * volume, partition, fileset and rootdir seem to be ignored | 295 | * volume, partition, fileset and rootdir seem to be ignored |
299 | * currently | 296 | * currently |
@@ -317,6 +314,8 @@ static int udf_show_options(struct seq_file *seq, struct vfsmount *mnt) | |||
317 | * | 314 | * |
318 | * gid= Set the default group. | 315 | * gid= Set the default group. |
319 | * umask= Set the default umask. | 316 | * umask= Set the default umask. |
317 | * mode= Set the default file permissions. | ||
318 | * dmode= Set the default directory permissions. | ||
320 | * uid= Set the default user. | 319 | * uid= Set the default user. |
321 | * bs= Set the block size. | 320 | * bs= Set the block size. |
322 | * unhide Show otherwise hidden files. | 321 | * unhide Show otherwise hidden files. |
@@ -366,7 +365,8 @@ enum { | |||
366 | Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock, | 365 | Opt_gid, Opt_uid, Opt_umask, Opt_session, Opt_lastblock, |
367 | Opt_anchor, Opt_volume, Opt_partition, Opt_fileset, | 366 | Opt_anchor, Opt_volume, Opt_partition, Opt_fileset, |
368 | Opt_rootdir, Opt_utf8, Opt_iocharset, | 367 | Opt_rootdir, Opt_utf8, Opt_iocharset, |
369 | Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore | 368 | Opt_err, Opt_uforget, Opt_uignore, Opt_gforget, Opt_gignore, |
369 | Opt_fmode, Opt_dmode | ||
370 | }; | 370 | }; |
371 | 371 | ||
372 | static const match_table_t tokens = { | 372 | static const match_table_t tokens = { |
@@ -395,6 +395,8 @@ static const match_table_t tokens = { | |||
395 | {Opt_rootdir, "rootdir=%u"}, | 395 | {Opt_rootdir, "rootdir=%u"}, |
396 | {Opt_utf8, "utf8"}, | 396 | {Opt_utf8, "utf8"}, |
397 | {Opt_iocharset, "iocharset=%s"}, | 397 | {Opt_iocharset, "iocharset=%s"}, |
398 | {Opt_fmode, "mode=%o"}, | ||
399 | {Opt_dmode, "dmode=%o"}, | ||
398 | {Opt_err, NULL} | 400 | {Opt_err, NULL} |
399 | }; | 401 | }; |
400 | 402 | ||
@@ -405,7 +407,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt, | |||
405 | int option; | 407 | int option; |
406 | 408 | ||
407 | uopt->novrs = 0; | 409 | uopt->novrs = 0; |
408 | uopt->blocksize = UDF_DEFAULT_BLOCKSIZE; | ||
409 | uopt->partition = 0xFFFF; | 410 | uopt->partition = 0xFFFF; |
410 | uopt->session = 0xFFFFFFFF; | 411 | uopt->session = 0xFFFFFFFF; |
411 | uopt->lastblock = 0; | 412 | uopt->lastblock = 0; |
@@ -428,10 +429,12 @@ static int udf_parse_options(char *options, struct udf_options *uopt, | |||
428 | switch (token) { | 429 | switch (token) { |
429 | case Opt_novrs: | 430 | case Opt_novrs: |
430 | uopt->novrs = 1; | 431 | uopt->novrs = 1; |
432 | break; | ||
431 | case Opt_bs: | 433 | case Opt_bs: |
432 | if (match_int(&args[0], &option)) | 434 | if (match_int(&args[0], &option)) |
433 | return 0; | 435 | return 0; |
434 | uopt->blocksize = option; | 436 | uopt->blocksize = option; |
437 | uopt->flags |= (1 << UDF_FLAG_BLOCKSIZE_SET); | ||
435 | break; | 438 | break; |
436 | case Opt_unhide: | 439 | case Opt_unhide: |
437 | uopt->flags |= (1 << UDF_FLAG_UNHIDE); | 440 | uopt->flags |= (1 << UDF_FLAG_UNHIDE); |
@@ -531,6 +534,16 @@ static int udf_parse_options(char *options, struct udf_options *uopt, | |||
531 | case Opt_gforget: | 534 | case Opt_gforget: |
532 | uopt->flags |= (1 << UDF_FLAG_GID_FORGET); | 535 | uopt->flags |= (1 << UDF_FLAG_GID_FORGET); |
533 | break; | 536 | break; |
537 | case Opt_fmode: | ||
538 | if (match_octal(args, &option)) | ||
539 | return 0; | ||
540 | uopt->fmode = option & 0777; | ||
541 | break; | ||
542 | case Opt_dmode: | ||
543 | if (match_octal(args, &option)) | ||
544 | return 0; | ||
545 | uopt->dmode = option & 0777; | ||
546 | break; | ||
534 | default: | 547 | default: |
535 | printk(KERN_ERR "udf: bad mount option \"%s\" " | 548 | printk(KERN_ERR "udf: bad mount option \"%s\" " |
536 | "or missing value\n", p); | 549 | "or missing value\n", p); |
@@ -540,17 +553,6 @@ static int udf_parse_options(char *options, struct udf_options *uopt, | |||
540 | return 1; | 553 | return 1; |
541 | } | 554 | } |
542 | 555 | ||
543 | static void udf_write_super(struct super_block *sb) | ||
544 | { | ||
545 | lock_kernel(); | ||
546 | |||
547 | if (!(sb->s_flags & MS_RDONLY)) | ||
548 | udf_open_lvid(sb); | ||
549 | sb->s_dirt = 0; | ||
550 | |||
551 | unlock_kernel(); | ||
552 | } | ||
553 | |||
554 | static int udf_remount_fs(struct super_block *sb, int *flags, char *options) | 556 | static int udf_remount_fs(struct super_block *sb, int *flags, char *options) |
555 | { | 557 | { |
556 | struct udf_options uopt; | 558 | struct udf_options uopt; |
@@ -560,6 +562,8 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) | |||
560 | uopt.uid = sbi->s_uid; | 562 | uopt.uid = sbi->s_uid; |
561 | uopt.gid = sbi->s_gid; | 563 | uopt.gid = sbi->s_gid; |
562 | uopt.umask = sbi->s_umask; | 564 | uopt.umask = sbi->s_umask; |
565 | uopt.fmode = sbi->s_fmode; | ||
566 | uopt.dmode = sbi->s_dmode; | ||
563 | 567 | ||
564 | if (!udf_parse_options(options, &uopt, true)) | 568 | if (!udf_parse_options(options, &uopt, true)) |
565 | return -EINVAL; | 569 | return -EINVAL; |
@@ -568,6 +572,8 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) | |||
568 | sbi->s_uid = uopt.uid; | 572 | sbi->s_uid = uopt.uid; |
569 | sbi->s_gid = uopt.gid; | 573 | sbi->s_gid = uopt.gid; |
570 | sbi->s_umask = uopt.umask; | 574 | sbi->s_umask = uopt.umask; |
575 | sbi->s_fmode = uopt.fmode; | ||
576 | sbi->s_dmode = uopt.dmode; | ||
571 | 577 | ||
572 | if (sbi->s_lvid_bh) { | 578 | if (sbi->s_lvid_bh) { |
573 | int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); | 579 | int write_rev = le16_to_cpu(udf_sb_lvidiu(sbi)->minUDFWriteRev); |
@@ -585,22 +591,19 @@ static int udf_remount_fs(struct super_block *sb, int *flags, char *options) | |||
585 | return 0; | 591 | return 0; |
586 | } | 592 | } |
587 | 593 | ||
588 | static int udf_vrs(struct super_block *sb, int silent) | 594 | /* Check Volume Structure Descriptors (ECMA 167 2/9.1) */ |
595 | /* We also check any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ | ||
596 | static loff_t udf_check_vsd(struct super_block *sb) | ||
589 | { | 597 | { |
590 | struct volStructDesc *vsd = NULL; | 598 | struct volStructDesc *vsd = NULL; |
591 | loff_t sector = 32768; | 599 | loff_t sector = 32768; |
592 | int sectorsize; | 600 | int sectorsize; |
593 | struct buffer_head *bh = NULL; | 601 | struct buffer_head *bh = NULL; |
594 | int iso9660 = 0; | ||
595 | int nsr02 = 0; | 602 | int nsr02 = 0; |
596 | int nsr03 = 0; | 603 | int nsr03 = 0; |
597 | struct udf_sb_info *sbi; | 604 | struct udf_sb_info *sbi; |
598 | 605 | ||
599 | /* Block size must be a multiple of 512 */ | ||
600 | if (sb->s_blocksize & 511) | ||
601 | return 0; | ||
602 | sbi = UDF_SB(sb); | 606 | sbi = UDF_SB(sb); |
603 | |||
604 | if (sb->s_blocksize < sizeof(struct volStructDesc)) | 607 | if (sb->s_blocksize < sizeof(struct volStructDesc)) |
605 | sectorsize = sizeof(struct volStructDesc); | 608 | sectorsize = sizeof(struct volStructDesc); |
606 | else | 609 | else |
@@ -627,7 +630,6 @@ static int udf_vrs(struct super_block *sb, int silent) | |||
627 | break; | 630 | break; |
628 | } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, | 631 | } else if (!strncmp(vsd->stdIdent, VSD_STD_ID_CD001, |
629 | VSD_STD_ID_LEN)) { | 632 | VSD_STD_ID_LEN)) { |
630 | iso9660 = sector; | ||
631 | switch (vsd->structType) { | 633 | switch (vsd->structType) { |
632 | case 0: | 634 | case 0: |
633 | udf_debug("ISO9660 Boot Record found\n"); | 635 | udf_debug("ISO9660 Boot Record found\n"); |
@@ -679,139 +681,9 @@ static int udf_vrs(struct super_block *sb, int silent) | |||
679 | return 0; | 681 | return 0; |
680 | } | 682 | } |
681 | 683 | ||
682 | /* | ||
683 | * Check whether there is an anchor block in the given block | ||
684 | */ | ||
685 | static int udf_check_anchor_block(struct super_block *sb, sector_t block) | ||
686 | { | ||
687 | struct buffer_head *bh; | ||
688 | uint16_t ident; | ||
689 | |||
690 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && | ||
691 | udf_fixed_to_variable(block) >= | ||
692 | sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) | ||
693 | return 0; | ||
694 | |||
695 | bh = udf_read_tagged(sb, block, block, &ident); | ||
696 | if (!bh) | ||
697 | return 0; | ||
698 | brelse(bh); | ||
699 | |||
700 | return ident == TAG_IDENT_AVDP; | ||
701 | } | ||
702 | |||
703 | /* Search for an anchor volume descriptor pointer */ | ||
704 | static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock) | ||
705 | { | ||
706 | sector_t last[6]; | ||
707 | int i; | ||
708 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
709 | |||
710 | last[0] = lastblock; | ||
711 | last[1] = last[0] - 1; | ||
712 | last[2] = last[0] + 1; | ||
713 | last[3] = last[0] - 2; | ||
714 | last[4] = last[0] - 150; | ||
715 | last[5] = last[0] - 152; | ||
716 | |||
717 | /* according to spec, anchor is in either: | ||
718 | * block 256 | ||
719 | * lastblock-256 | ||
720 | * lastblock | ||
721 | * however, if the disc isn't closed, it could be 512 */ | ||
722 | |||
723 | for (i = 0; i < ARRAY_SIZE(last); i++) { | ||
724 | if (last[i] < 0) | ||
725 | continue; | ||
726 | if (last[i] >= sb->s_bdev->bd_inode->i_size >> | ||
727 | sb->s_blocksize_bits) | ||
728 | continue; | ||
729 | |||
730 | if (udf_check_anchor_block(sb, last[i])) { | ||
731 | sbi->s_anchor[0] = last[i]; | ||
732 | sbi->s_anchor[1] = last[i] - 256; | ||
733 | return last[i]; | ||
734 | } | ||
735 | |||
736 | if (last[i] < 256) | ||
737 | continue; | ||
738 | |||
739 | if (udf_check_anchor_block(sb, last[i] - 256)) { | ||
740 | sbi->s_anchor[1] = last[i] - 256; | ||
741 | return last[i]; | ||
742 | } | ||
743 | } | ||
744 | |||
745 | if (udf_check_anchor_block(sb, sbi->s_session + 256)) { | ||
746 | sbi->s_anchor[0] = sbi->s_session + 256; | ||
747 | return last[0]; | ||
748 | } | ||
749 | if (udf_check_anchor_block(sb, sbi->s_session + 512)) { | ||
750 | sbi->s_anchor[0] = sbi->s_session + 512; | ||
751 | return last[0]; | ||
752 | } | ||
753 | return 0; | ||
754 | } | ||
755 | |||
756 | /* | ||
757 | * Find an anchor volume descriptor. The function expects sbi->s_lastblock to | ||
758 | * be the last block on the media. | ||
759 | * | ||
760 | * Return 1 if not found, 0 if ok | ||
761 | * | ||
762 | */ | ||
763 | static void udf_find_anchor(struct super_block *sb) | ||
764 | { | ||
765 | sector_t lastblock; | ||
766 | struct buffer_head *bh = NULL; | ||
767 | uint16_t ident; | ||
768 | int i; | ||
769 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
770 | |||
771 | lastblock = udf_scan_anchors(sb, sbi->s_last_block); | ||
772 | if (lastblock) | ||
773 | goto check_anchor; | ||
774 | |||
775 | /* No anchor found? Try VARCONV conversion of block numbers */ | ||
776 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
777 | /* Firstly, we try to not convert number of the last block */ | ||
778 | lastblock = udf_scan_anchors(sb, | ||
779 | udf_variable_to_fixed(sbi->s_last_block)); | ||
780 | if (lastblock) | ||
781 | goto check_anchor; | ||
782 | |||
783 | /* Secondly, we try with converted number of the last block */ | ||
784 | lastblock = udf_scan_anchors(sb, sbi->s_last_block); | ||
785 | if (!lastblock) { | ||
786 | /* VARCONV didn't help. Clear it. */ | ||
787 | UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); | ||
788 | } | ||
789 | |||
790 | check_anchor: | ||
791 | /* | ||
792 | * Check located anchors and the anchor block supplied via | ||
793 | * mount options | ||
794 | */ | ||
795 | for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { | ||
796 | if (!sbi->s_anchor[i]) | ||
797 | continue; | ||
798 | bh = udf_read_tagged(sb, sbi->s_anchor[i], | ||
799 | sbi->s_anchor[i], &ident); | ||
800 | if (!bh) | ||
801 | sbi->s_anchor[i] = 0; | ||
802 | else { | ||
803 | brelse(bh); | ||
804 | if (ident != TAG_IDENT_AVDP) | ||
805 | sbi->s_anchor[i] = 0; | ||
806 | } | ||
807 | } | ||
808 | |||
809 | sbi->s_last_block = lastblock; | ||
810 | } | ||
811 | |||
812 | static int udf_find_fileset(struct super_block *sb, | 684 | static int udf_find_fileset(struct super_block *sb, |
813 | kernel_lb_addr *fileset, | 685 | struct kernel_lb_addr *fileset, |
814 | kernel_lb_addr *root) | 686 | struct kernel_lb_addr *root) |
815 | { | 687 | { |
816 | struct buffer_head *bh = NULL; | 688 | struct buffer_head *bh = NULL; |
817 | long lastblock; | 689 | long lastblock; |
@@ -820,7 +692,7 @@ static int udf_find_fileset(struct super_block *sb, | |||
820 | 692 | ||
821 | if (fileset->logicalBlockNum != 0xFFFFFFFF || | 693 | if (fileset->logicalBlockNum != 0xFFFFFFFF || |
822 | fileset->partitionReferenceNum != 0xFFFF) { | 694 | fileset->partitionReferenceNum != 0xFFFF) { |
823 | bh = udf_read_ptagged(sb, *fileset, 0, &ident); | 695 | bh = udf_read_ptagged(sb, fileset, 0, &ident); |
824 | 696 | ||
825 | if (!bh) { | 697 | if (!bh) { |
826 | return 1; | 698 | return 1; |
@@ -834,7 +706,7 @@ static int udf_find_fileset(struct super_block *sb, | |||
834 | sbi = UDF_SB(sb); | 706 | sbi = UDF_SB(sb); |
835 | if (!bh) { | 707 | if (!bh) { |
836 | /* Search backwards through the partitions */ | 708 | /* Search backwards through the partitions */ |
837 | kernel_lb_addr newfileset; | 709 | struct kernel_lb_addr newfileset; |
838 | 710 | ||
839 | /* --> cvg: FIXME - is it reasonable? */ | 711 | /* --> cvg: FIXME - is it reasonable? */ |
840 | return 1; | 712 | return 1; |
@@ -850,7 +722,7 @@ static int udf_find_fileset(struct super_block *sb, | |||
850 | newfileset.logicalBlockNum = 0; | 722 | newfileset.logicalBlockNum = 0; |
851 | 723 | ||
852 | do { | 724 | do { |
853 | bh = udf_read_ptagged(sb, newfileset, 0, | 725 | bh = udf_read_ptagged(sb, &newfileset, 0, |
854 | &ident); | 726 | &ident); |
855 | if (!bh) { | 727 | if (!bh) { |
856 | newfileset.logicalBlockNum++; | 728 | newfileset.logicalBlockNum++; |
@@ -902,14 +774,23 @@ static int udf_find_fileset(struct super_block *sb, | |||
902 | static int udf_load_pvoldesc(struct super_block *sb, sector_t block) | 774 | static int udf_load_pvoldesc(struct super_block *sb, sector_t block) |
903 | { | 775 | { |
904 | struct primaryVolDesc *pvoldesc; | 776 | struct primaryVolDesc *pvoldesc; |
905 | struct ustr instr; | 777 | struct ustr *instr, *outstr; |
906 | struct ustr outstr; | ||
907 | struct buffer_head *bh; | 778 | struct buffer_head *bh; |
908 | uint16_t ident; | 779 | uint16_t ident; |
780 | int ret = 1; | ||
781 | |||
782 | instr = kmalloc(sizeof(struct ustr), GFP_NOFS); | ||
783 | if (!instr) | ||
784 | return 1; | ||
785 | |||
786 | outstr = kmalloc(sizeof(struct ustr), GFP_NOFS); | ||
787 | if (!outstr) | ||
788 | goto out1; | ||
909 | 789 | ||
910 | bh = udf_read_tagged(sb, block, block, &ident); | 790 | bh = udf_read_tagged(sb, block, block, &ident); |
911 | if (!bh) | 791 | if (!bh) |
912 | return 1; | 792 | goto out2; |
793 | |||
913 | BUG_ON(ident != TAG_IDENT_PVD); | 794 | BUG_ON(ident != TAG_IDENT_PVD); |
914 | 795 | ||
915 | pvoldesc = (struct primaryVolDesc *)bh->b_data; | 796 | pvoldesc = (struct primaryVolDesc *)bh->b_data; |
@@ -917,7 +798,7 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) | |||
917 | if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time, | 798 | if (udf_disk_stamp_to_time(&UDF_SB(sb)->s_record_time, |
918 | pvoldesc->recordingDateAndTime)) { | 799 | pvoldesc->recordingDateAndTime)) { |
919 | #ifdef UDFFS_DEBUG | 800 | #ifdef UDFFS_DEBUG |
920 | timestamp *ts = &pvoldesc->recordingDateAndTime; | 801 | struct timestamp *ts = &pvoldesc->recordingDateAndTime; |
921 | udf_debug("recording time %04u/%02u/%02u" | 802 | udf_debug("recording time %04u/%02u/%02u" |
922 | " %02u:%02u (%x)\n", | 803 | " %02u:%02u (%x)\n", |
923 | le16_to_cpu(ts->year), ts->month, ts->day, ts->hour, | 804 | le16_to_cpu(ts->year), ts->month, ts->day, ts->hour, |
@@ -925,20 +806,25 @@ static int udf_load_pvoldesc(struct super_block *sb, sector_t block) | |||
925 | #endif | 806 | #endif |
926 | } | 807 | } |
927 | 808 | ||
928 | if (!udf_build_ustr(&instr, pvoldesc->volIdent, 32)) | 809 | if (!udf_build_ustr(instr, pvoldesc->volIdent, 32)) |
929 | if (udf_CS0toUTF8(&outstr, &instr)) { | 810 | if (udf_CS0toUTF8(outstr, instr)) { |
930 | strncpy(UDF_SB(sb)->s_volume_ident, outstr.u_name, | 811 | strncpy(UDF_SB(sb)->s_volume_ident, outstr->u_name, |
931 | outstr.u_len > 31 ? 31 : outstr.u_len); | 812 | outstr->u_len > 31 ? 31 : outstr->u_len); |
932 | udf_debug("volIdent[] = '%s'\n", | 813 | udf_debug("volIdent[] = '%s'\n", |
933 | UDF_SB(sb)->s_volume_ident); | 814 | UDF_SB(sb)->s_volume_ident); |
934 | } | 815 | } |
935 | 816 | ||
936 | if (!udf_build_ustr(&instr, pvoldesc->volSetIdent, 128)) | 817 | if (!udf_build_ustr(instr, pvoldesc->volSetIdent, 128)) |
937 | if (udf_CS0toUTF8(&outstr, &instr)) | 818 | if (udf_CS0toUTF8(outstr, instr)) |
938 | udf_debug("volSetIdent[] = '%s'\n", outstr.u_name); | 819 | udf_debug("volSetIdent[] = '%s'\n", outstr->u_name); |
939 | 820 | ||
940 | brelse(bh); | 821 | brelse(bh); |
941 | return 0; | 822 | ret = 0; |
823 | out2: | ||
824 | kfree(outstr); | ||
825 | out1: | ||
826 | kfree(instr); | ||
827 | return ret; | ||
942 | } | 828 | } |
943 | 829 | ||
944 | static int udf_load_metadata_files(struct super_block *sb, int partition) | 830 | static int udf_load_metadata_files(struct super_block *sb, int partition) |
@@ -946,7 +832,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) | |||
946 | struct udf_sb_info *sbi = UDF_SB(sb); | 832 | struct udf_sb_info *sbi = UDF_SB(sb); |
947 | struct udf_part_map *map; | 833 | struct udf_part_map *map; |
948 | struct udf_meta_data *mdata; | 834 | struct udf_meta_data *mdata; |
949 | kernel_lb_addr addr; | 835 | struct kernel_lb_addr addr; |
950 | int fe_error = 0; | 836 | int fe_error = 0; |
951 | 837 | ||
952 | map = &sbi->s_partmaps[partition]; | 838 | map = &sbi->s_partmaps[partition]; |
@@ -959,7 +845,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) | |||
959 | udf_debug("Metadata file location: block = %d part = %d\n", | 845 | udf_debug("Metadata file location: block = %d part = %d\n", |
960 | addr.logicalBlockNum, addr.partitionReferenceNum); | 846 | addr.logicalBlockNum, addr.partitionReferenceNum); |
961 | 847 | ||
962 | mdata->s_metadata_fe = udf_iget(sb, addr); | 848 | mdata->s_metadata_fe = udf_iget(sb, &addr); |
963 | 849 | ||
964 | if (mdata->s_metadata_fe == NULL) { | 850 | if (mdata->s_metadata_fe == NULL) { |
965 | udf_warning(sb, __func__, "metadata inode efe not found, " | 851 | udf_warning(sb, __func__, "metadata inode efe not found, " |
@@ -981,7 +867,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) | |||
981 | udf_debug("Mirror metadata file location: block = %d part = %d\n", | 867 | udf_debug("Mirror metadata file location: block = %d part = %d\n", |
982 | addr.logicalBlockNum, addr.partitionReferenceNum); | 868 | addr.logicalBlockNum, addr.partitionReferenceNum); |
983 | 869 | ||
984 | mdata->s_mirror_fe = udf_iget(sb, addr); | 870 | mdata->s_mirror_fe = udf_iget(sb, &addr); |
985 | 871 | ||
986 | if (mdata->s_mirror_fe == NULL) { | 872 | if (mdata->s_mirror_fe == NULL) { |
987 | if (fe_error) { | 873 | if (fe_error) { |
@@ -1013,7 +899,7 @@ static int udf_load_metadata_files(struct super_block *sb, int partition) | |||
1013 | udf_debug("Bitmap file location: block = %d part = %d\n", | 899 | udf_debug("Bitmap file location: block = %d part = %d\n", |
1014 | addr.logicalBlockNum, addr.partitionReferenceNum); | 900 | addr.logicalBlockNum, addr.partitionReferenceNum); |
1015 | 901 | ||
1016 | mdata->s_bitmap_fe = udf_iget(sb, addr); | 902 | mdata->s_bitmap_fe = udf_iget(sb, &addr); |
1017 | 903 | ||
1018 | if (mdata->s_bitmap_fe == NULL) { | 904 | if (mdata->s_bitmap_fe == NULL) { |
1019 | if (sb->s_flags & MS_RDONLY) | 905 | if (sb->s_flags & MS_RDONLY) |
@@ -1037,7 +923,7 @@ error_exit: | |||
1037 | } | 923 | } |
1038 | 924 | ||
1039 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, | 925 | static void udf_load_fileset(struct super_block *sb, struct buffer_head *bh, |
1040 | kernel_lb_addr *root) | 926 | struct kernel_lb_addr *root) |
1041 | { | 927 | { |
1042 | struct fileSetDesc *fset; | 928 | struct fileSetDesc *fset; |
1043 | 929 | ||
@@ -1119,13 +1005,13 @@ static int udf_fill_partdesc_info(struct super_block *sb, | |||
1119 | 1005 | ||
1120 | phd = (struct partitionHeaderDesc *)p->partitionContentsUse; | 1006 | phd = (struct partitionHeaderDesc *)p->partitionContentsUse; |
1121 | if (phd->unallocSpaceTable.extLength) { | 1007 | if (phd->unallocSpaceTable.extLength) { |
1122 | kernel_lb_addr loc = { | 1008 | struct kernel_lb_addr loc = { |
1123 | .logicalBlockNum = le32_to_cpu( | 1009 | .logicalBlockNum = le32_to_cpu( |
1124 | phd->unallocSpaceTable.extPosition), | 1010 | phd->unallocSpaceTable.extPosition), |
1125 | .partitionReferenceNum = p_index, | 1011 | .partitionReferenceNum = p_index, |
1126 | }; | 1012 | }; |
1127 | 1013 | ||
1128 | map->s_uspace.s_table = udf_iget(sb, loc); | 1014 | map->s_uspace.s_table = udf_iget(sb, &loc); |
1129 | if (!map->s_uspace.s_table) { | 1015 | if (!map->s_uspace.s_table) { |
1130 | udf_debug("cannot load unallocSpaceTable (part %d)\n", | 1016 | udf_debug("cannot load unallocSpaceTable (part %d)\n", |
1131 | p_index); | 1017 | p_index); |
@@ -1154,13 +1040,13 @@ static int udf_fill_partdesc_info(struct super_block *sb, | |||
1154 | udf_debug("partitionIntegrityTable (part %d)\n", p_index); | 1040 | udf_debug("partitionIntegrityTable (part %d)\n", p_index); |
1155 | 1041 | ||
1156 | if (phd->freedSpaceTable.extLength) { | 1042 | if (phd->freedSpaceTable.extLength) { |
1157 | kernel_lb_addr loc = { | 1043 | struct kernel_lb_addr loc = { |
1158 | .logicalBlockNum = le32_to_cpu( | 1044 | .logicalBlockNum = le32_to_cpu( |
1159 | phd->freedSpaceTable.extPosition), | 1045 | phd->freedSpaceTable.extPosition), |
1160 | .partitionReferenceNum = p_index, | 1046 | .partitionReferenceNum = p_index, |
1161 | }; | 1047 | }; |
1162 | 1048 | ||
1163 | map->s_fspace.s_table = udf_iget(sb, loc); | 1049 | map->s_fspace.s_table = udf_iget(sb, &loc); |
1164 | if (!map->s_fspace.s_table) { | 1050 | if (!map->s_fspace.s_table) { |
1165 | udf_debug("cannot load freedSpaceTable (part %d)\n", | 1051 | udf_debug("cannot load freedSpaceTable (part %d)\n", |
1166 | p_index); | 1052 | p_index); |
@@ -1192,7 +1078,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
1192 | { | 1078 | { |
1193 | struct udf_sb_info *sbi = UDF_SB(sb); | 1079 | struct udf_sb_info *sbi = UDF_SB(sb); |
1194 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; | 1080 | struct udf_part_map *map = &sbi->s_partmaps[p_index]; |
1195 | kernel_lb_addr ino; | 1081 | struct kernel_lb_addr ino; |
1196 | struct buffer_head *bh = NULL; | 1082 | struct buffer_head *bh = NULL; |
1197 | struct udf_inode_info *vati; | 1083 | struct udf_inode_info *vati; |
1198 | uint32_t pos; | 1084 | uint32_t pos; |
@@ -1201,7 +1087,7 @@ static int udf_load_vat(struct super_block *sb, int p_index, int type1_index) | |||
1201 | /* VAT file entry is in the last recorded block */ | 1087 | /* VAT file entry is in the last recorded block */ |
1202 | ino.partitionReferenceNum = type1_index; | 1088 | ino.partitionReferenceNum = type1_index; |
1203 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; | 1089 | ino.logicalBlockNum = sbi->s_last_block - map->s_partition_root; |
1204 | sbi->s_vat_inode = udf_iget(sb, ino); | 1090 | sbi->s_vat_inode = udf_iget(sb, &ino); |
1205 | if (!sbi->s_vat_inode) | 1091 | if (!sbi->s_vat_inode) |
1206 | return 1; | 1092 | return 1; |
1207 | 1093 | ||
@@ -1322,7 +1208,7 @@ out_bh: | |||
1322 | } | 1208 | } |
1323 | 1209 | ||
1324 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, | 1210 | static int udf_load_logicalvol(struct super_block *sb, sector_t block, |
1325 | kernel_lb_addr *fileset) | 1211 | struct kernel_lb_addr *fileset) |
1326 | { | 1212 | { |
1327 | struct logicalVolDesc *lvd; | 1213 | struct logicalVolDesc *lvd; |
1328 | int i, j, offset; | 1214 | int i, j, offset; |
@@ -1471,7 +1357,7 @@ static int udf_load_logicalvol(struct super_block *sb, sector_t block, | |||
1471 | } | 1357 | } |
1472 | 1358 | ||
1473 | if (fileset) { | 1359 | if (fileset) { |
1474 | long_ad *la = (long_ad *)&(lvd->logicalVolContentsUse[0]); | 1360 | struct long_ad *la = (struct long_ad *)&(lvd->logicalVolContentsUse[0]); |
1475 | 1361 | ||
1476 | *fileset = lelb_to_cpu(la->extLocation); | 1362 | *fileset = lelb_to_cpu(la->extLocation); |
1477 | udf_debug("FileSet found in LogicalVolDesc at block=%d, " | 1363 | udf_debug("FileSet found in LogicalVolDesc at block=%d, " |
@@ -1490,7 +1376,7 @@ out_bh: | |||
1490 | * udf_load_logicalvolint | 1376 | * udf_load_logicalvolint |
1491 | * | 1377 | * |
1492 | */ | 1378 | */ |
1493 | static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc) | 1379 | static void udf_load_logicalvolint(struct super_block *sb, struct kernel_extent_ad loc) |
1494 | { | 1380 | { |
1495 | struct buffer_head *bh = NULL; | 1381 | struct buffer_head *bh = NULL; |
1496 | uint16_t ident; | 1382 | uint16_t ident; |
@@ -1533,7 +1419,7 @@ static void udf_load_logicalvolint(struct super_block *sb, kernel_extent_ad loc) | |||
1533 | * Written, tested, and released. | 1419 | * Written, tested, and released. |
1534 | */ | 1420 | */ |
1535 | static noinline int udf_process_sequence(struct super_block *sb, long block, | 1421 | static noinline int udf_process_sequence(struct super_block *sb, long block, |
1536 | long lastblock, kernel_lb_addr *fileset) | 1422 | long lastblock, struct kernel_lb_addr *fileset) |
1537 | { | 1423 | { |
1538 | struct buffer_head *bh = NULL; | 1424 | struct buffer_head *bh = NULL; |
1539 | struct udf_vds_record vds[VDS_POS_LENGTH]; | 1425 | struct udf_vds_record vds[VDS_POS_LENGTH]; |
@@ -1655,85 +1541,199 @@ static noinline int udf_process_sequence(struct super_block *sb, long block, | |||
1655 | return 0; | 1541 | return 0; |
1656 | } | 1542 | } |
1657 | 1543 | ||
1544 | static int udf_load_sequence(struct super_block *sb, struct buffer_head *bh, | ||
1545 | struct kernel_lb_addr *fileset) | ||
1546 | { | ||
1547 | struct anchorVolDescPtr *anchor; | ||
1548 | long main_s, main_e, reserve_s, reserve_e; | ||
1549 | struct udf_sb_info *sbi; | ||
1550 | |||
1551 | sbi = UDF_SB(sb); | ||
1552 | anchor = (struct anchorVolDescPtr *)bh->b_data; | ||
1553 | |||
1554 | /* Locate the main sequence */ | ||
1555 | main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation); | ||
1556 | main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength); | ||
1557 | main_e = main_e >> sb->s_blocksize_bits; | ||
1558 | main_e += main_s; | ||
1559 | |||
1560 | /* Locate the reserve sequence */ | ||
1561 | reserve_s = le32_to_cpu(anchor->reserveVolDescSeqExt.extLocation); | ||
1562 | reserve_e = le32_to_cpu(anchor->reserveVolDescSeqExt.extLength); | ||
1563 | reserve_e = reserve_e >> sb->s_blocksize_bits; | ||
1564 | reserve_e += reserve_s; | ||
1565 | |||
1566 | /* Process the main & reserve sequences */ | ||
1567 | /* responsible for finding the PartitionDesc(s) */ | ||
1568 | if (!udf_process_sequence(sb, main_s, main_e, fileset)) | ||
1569 | return 1; | ||
1570 | return !udf_process_sequence(sb, reserve_s, reserve_e, fileset); | ||
1571 | } | ||
1572 | |||
1658 | /* | 1573 | /* |
1659 | * udf_check_valid() | 1574 | * Check whether there is an anchor block in the given block and |
1575 | * load Volume Descriptor Sequence if so. | ||
1660 | */ | 1576 | */ |
1661 | static int udf_check_valid(struct super_block *sb, int novrs, int silent) | 1577 | static int udf_check_anchor_block(struct super_block *sb, sector_t block, |
1578 | struct kernel_lb_addr *fileset) | ||
1662 | { | 1579 | { |
1663 | long block; | 1580 | struct buffer_head *bh; |
1664 | struct udf_sb_info *sbi = UDF_SB(sb); | 1581 | uint16_t ident; |
1582 | int ret; | ||
1665 | 1583 | ||
1666 | if (novrs) { | 1584 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_VARCONV) && |
1667 | udf_debug("Validity check skipped because of novrs option\n"); | 1585 | udf_fixed_to_variable(block) >= |
1586 | sb->s_bdev->bd_inode->i_size >> sb->s_blocksize_bits) | ||
1587 | return 0; | ||
1588 | |||
1589 | bh = udf_read_tagged(sb, block, block, &ident); | ||
1590 | if (!bh) | ||
1591 | return 0; | ||
1592 | if (ident != TAG_IDENT_AVDP) { | ||
1593 | brelse(bh); | ||
1668 | return 0; | 1594 | return 0; |
1669 | } | 1595 | } |
1670 | /* Check that it is NSR02 compliant */ | 1596 | ret = udf_load_sequence(sb, bh, fileset); |
1671 | /* Process any "CD-ROM Volume Descriptor Set" (ECMA 167 2/8.3.1) */ | 1597 | brelse(bh); |
1672 | block = udf_vrs(sb, silent); | 1598 | return ret; |
1673 | if (block == -1) | ||
1674 | udf_debug("Failed to read byte 32768. Assuming open " | ||
1675 | "disc. Skipping validity check\n"); | ||
1676 | if (block && !sbi->s_last_block) | ||
1677 | sbi->s_last_block = udf_get_last_block(sb); | ||
1678 | return !block; | ||
1679 | } | 1599 | } |
1680 | 1600 | ||
1681 | static int udf_load_sequence(struct super_block *sb, kernel_lb_addr *fileset) | 1601 | /* Search for an anchor volume descriptor pointer */ |
1602 | static sector_t udf_scan_anchors(struct super_block *sb, sector_t lastblock, | ||
1603 | struct kernel_lb_addr *fileset) | ||
1682 | { | 1604 | { |
1683 | struct anchorVolDescPtr *anchor; | 1605 | sector_t last[6]; |
1684 | uint16_t ident; | ||
1685 | struct buffer_head *bh; | ||
1686 | long main_s, main_e, reserve_s, reserve_e; | ||
1687 | int i; | 1606 | int i; |
1688 | struct udf_sb_info *sbi; | 1607 | struct udf_sb_info *sbi = UDF_SB(sb); |
1689 | 1608 | int last_count = 0; | |
1690 | if (!sb) | ||
1691 | return 1; | ||
1692 | sbi = UDF_SB(sb); | ||
1693 | 1609 | ||
1694 | for (i = 0; i < ARRAY_SIZE(sbi->s_anchor); i++) { | 1610 | /* First try user provided anchor */ |
1695 | if (!sbi->s_anchor[i]) | 1611 | if (sbi->s_anchor) { |
1612 | if (udf_check_anchor_block(sb, sbi->s_anchor, fileset)) | ||
1613 | return lastblock; | ||
1614 | } | ||
1615 | /* | ||
1616 | * according to spec, anchor is in either: | ||
1617 | * block 256 | ||
1618 | * lastblock-256 | ||
1619 | * lastblock | ||
1620 | * however, if the disc isn't closed, it could be 512. | ||
1621 | */ | ||
1622 | if (udf_check_anchor_block(sb, sbi->s_session + 256, fileset)) | ||
1623 | return lastblock; | ||
1624 | /* | ||
1625 | * The trouble is which block is the last one. Drives often misreport | ||
1626 | * this so we try various possibilities. | ||
1627 | */ | ||
1628 | last[last_count++] = lastblock; | ||
1629 | if (lastblock >= 1) | ||
1630 | last[last_count++] = lastblock - 1; | ||
1631 | last[last_count++] = lastblock + 1; | ||
1632 | if (lastblock >= 2) | ||
1633 | last[last_count++] = lastblock - 2; | ||
1634 | if (lastblock >= 150) | ||
1635 | last[last_count++] = lastblock - 150; | ||
1636 | if (lastblock >= 152) | ||
1637 | last[last_count++] = lastblock - 152; | ||
1638 | |||
1639 | for (i = 0; i < last_count; i++) { | ||
1640 | if (last[i] >= sb->s_bdev->bd_inode->i_size >> | ||
1641 | sb->s_blocksize_bits) | ||
1696 | continue; | 1642 | continue; |
1697 | 1643 | if (udf_check_anchor_block(sb, last[i], fileset)) | |
1698 | bh = udf_read_tagged(sb, sbi->s_anchor[i], sbi->s_anchor[i], | 1644 | return last[i]; |
1699 | &ident); | 1645 | if (last[i] < 256) |
1700 | if (!bh) | ||
1701 | continue; | 1646 | continue; |
1647 | if (udf_check_anchor_block(sb, last[i] - 256, fileset)) | ||
1648 | return last[i]; | ||
1649 | } | ||
1702 | 1650 | ||
1703 | anchor = (struct anchorVolDescPtr *)bh->b_data; | 1651 | /* Finally try block 512 in case media is open */ |
1652 | if (udf_check_anchor_block(sb, sbi->s_session + 512, fileset)) | ||
1653 | return last[0]; | ||
1654 | return 0; | ||
1655 | } | ||
1704 | 1656 | ||
1705 | /* Locate the main sequence */ | 1657 | /* |
1706 | main_s = le32_to_cpu(anchor->mainVolDescSeqExt.extLocation); | 1658 | * Find an anchor volume descriptor and load Volume Descriptor Sequence from |
1707 | main_e = le32_to_cpu(anchor->mainVolDescSeqExt.extLength); | 1659 | * area specified by it. The function expects sbi->s_lastblock to be the last |
1708 | main_e = main_e >> sb->s_blocksize_bits; | 1660 | * block on the media. |
1709 | main_e += main_s; | 1661 | * |
1662 | * Return 1 if ok, 0 if not found. | ||
1663 | * | ||
1664 | */ | ||
1665 | static int udf_find_anchor(struct super_block *sb, | ||
1666 | struct kernel_lb_addr *fileset) | ||
1667 | { | ||
1668 | sector_t lastblock; | ||
1669 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1710 | 1670 | ||
1711 | /* Locate the reserve sequence */ | 1671 | lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); |
1712 | reserve_s = le32_to_cpu( | 1672 | if (lastblock) |
1713 | anchor->reserveVolDescSeqExt.extLocation); | 1673 | goto out; |
1714 | reserve_e = le32_to_cpu( | ||
1715 | anchor->reserveVolDescSeqExt.extLength); | ||
1716 | reserve_e = reserve_e >> sb->s_blocksize_bits; | ||
1717 | reserve_e += reserve_s; | ||
1718 | 1674 | ||
1719 | brelse(bh); | 1675 | /* No anchor found? Try VARCONV conversion of block numbers */ |
1676 | UDF_SET_FLAG(sb, UDF_FLAG_VARCONV); | ||
1677 | /* Firstly, we try to not convert number of the last block */ | ||
1678 | lastblock = udf_scan_anchors(sb, | ||
1679 | udf_variable_to_fixed(sbi->s_last_block), | ||
1680 | fileset); | ||
1681 | if (lastblock) | ||
1682 | goto out; | ||
1720 | 1683 | ||
1721 | /* Process the main & reserve sequences */ | 1684 | /* Secondly, we try with converted number of the last block */ |
1722 | /* responsible for finding the PartitionDesc(s) */ | 1685 | lastblock = udf_scan_anchors(sb, sbi->s_last_block, fileset); |
1723 | if (!(udf_process_sequence(sb, main_s, main_e, | 1686 | if (!lastblock) { |
1724 | fileset) && | 1687 | /* VARCONV didn't help. Clear it. */ |
1725 | udf_process_sequence(sb, reserve_s, reserve_e, | 1688 | UDF_CLEAR_FLAG(sb, UDF_FLAG_VARCONV); |
1726 | fileset))) | 1689 | return 0; |
1727 | break; | ||
1728 | } | 1690 | } |
1691 | out: | ||
1692 | sbi->s_last_block = lastblock; | ||
1693 | return 1; | ||
1694 | } | ||
1729 | 1695 | ||
1730 | if (i == ARRAY_SIZE(sbi->s_anchor)) { | 1696 | /* |
1731 | udf_debug("No Anchor block found\n"); | 1697 | * Check Volume Structure Descriptor, find Anchor block and load Volume |
1732 | return 1; | 1698 | * Descriptor Sequence |
1699 | */ | ||
1700 | static int udf_load_vrs(struct super_block *sb, struct udf_options *uopt, | ||
1701 | int silent, struct kernel_lb_addr *fileset) | ||
1702 | { | ||
1703 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
1704 | loff_t nsr_off; | ||
1705 | |||
1706 | if (!sb_set_blocksize(sb, uopt->blocksize)) { | ||
1707 | if (!silent) | ||
1708 | printk(KERN_WARNING "UDF-fs: Bad block size\n"); | ||
1709 | return 0; | ||
1710 | } | ||
1711 | sbi->s_last_block = uopt->lastblock; | ||
1712 | if (!uopt->novrs) { | ||
1713 | /* Check that it is NSR02 compliant */ | ||
1714 | nsr_off = udf_check_vsd(sb); | ||
1715 | if (!nsr_off) { | ||
1716 | if (!silent) | ||
1717 | printk(KERN_WARNING "UDF-fs: No VRS found\n"); | ||
1718 | return 0; | ||
1719 | } | ||
1720 | if (nsr_off == -1) | ||
1721 | udf_debug("Failed to read byte 32768. Assuming open " | ||
1722 | "disc. Skipping validity check\n"); | ||
1723 | if (!sbi->s_last_block) | ||
1724 | sbi->s_last_block = udf_get_last_block(sb); | ||
1725 | } else { | ||
1726 | udf_debug("Validity check skipped because of novrs option\n"); | ||
1733 | } | 1727 | } |
1734 | udf_debug("Using anchor in block %d\n", sbi->s_anchor[i]); | ||
1735 | 1728 | ||
1736 | return 0; | 1729 | /* Look for anchor block and load Volume Descriptor Sequence */ |
1730 | sbi->s_anchor = uopt->anchor; | ||
1731 | if (!udf_find_anchor(sb, fileset)) { | ||
1732 | if (!silent) | ||
1733 | printk(KERN_WARNING "UDF-fs: No anchor found\n"); | ||
1734 | return 0; | ||
1735 | } | ||
1736 | return 1; | ||
1737 | } | 1737 | } |
1738 | 1738 | ||
1739 | static void udf_open_lvid(struct super_block *sb) | 1739 | static void udf_open_lvid(struct super_block *sb) |
@@ -1742,9 +1742,9 @@ static void udf_open_lvid(struct super_block *sb) | |||
1742 | struct buffer_head *bh = sbi->s_lvid_bh; | 1742 | struct buffer_head *bh = sbi->s_lvid_bh; |
1743 | struct logicalVolIntegrityDesc *lvid; | 1743 | struct logicalVolIntegrityDesc *lvid; |
1744 | struct logicalVolIntegrityDescImpUse *lvidiu; | 1744 | struct logicalVolIntegrityDescImpUse *lvidiu; |
1745 | |||
1745 | if (!bh) | 1746 | if (!bh) |
1746 | return; | 1747 | return; |
1747 | |||
1748 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | 1748 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; |
1749 | lvidiu = udf_sb_lvidiu(sbi); | 1749 | lvidiu = udf_sb_lvidiu(sbi); |
1750 | 1750 | ||
@@ -1752,14 +1752,15 @@ static void udf_open_lvid(struct super_block *sb) | |||
1752 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1752 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
1753 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, | 1753 | udf_time_to_disk_stamp(&lvid->recordingDateAndTime, |
1754 | CURRENT_TIME); | 1754 | CURRENT_TIME); |
1755 | lvid->integrityType = LVID_INTEGRITY_TYPE_OPEN; | 1755 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN); |
1756 | 1756 | ||
1757 | lvid->descTag.descCRC = cpu_to_le16( | 1757 | lvid->descTag.descCRC = cpu_to_le16( |
1758 | crc_itu_t(0, (char *)lvid + sizeof(tag), | 1758 | crc_itu_t(0, (char *)lvid + sizeof(struct tag), |
1759 | le16_to_cpu(lvid->descTag.descCRCLength))); | 1759 | le16_to_cpu(lvid->descTag.descCRCLength))); |
1760 | 1760 | ||
1761 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); | 1761 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
1762 | mark_buffer_dirty(bh); | 1762 | mark_buffer_dirty(bh); |
1763 | sbi->s_lvid_dirty = 0; | ||
1763 | } | 1764 | } |
1764 | 1765 | ||
1765 | static void udf_close_lvid(struct super_block *sb) | 1766 | static void udf_close_lvid(struct super_block *sb) |
@@ -1773,10 +1774,6 @@ static void udf_close_lvid(struct super_block *sb) | |||
1773 | return; | 1774 | return; |
1774 | 1775 | ||
1775 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; | 1776 | lvid = (struct logicalVolIntegrityDesc *)bh->b_data; |
1776 | |||
1777 | if (lvid->integrityType != LVID_INTEGRITY_TYPE_OPEN) | ||
1778 | return; | ||
1779 | |||
1780 | lvidiu = udf_sb_lvidiu(sbi); | 1777 | lvidiu = udf_sb_lvidiu(sbi); |
1781 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; | 1778 | lvidiu->impIdent.identSuffix[0] = UDF_OS_CLASS_UNIX; |
1782 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; | 1779 | lvidiu->impIdent.identSuffix[1] = UDF_OS_ID_LINUX; |
@@ -1790,11 +1787,12 @@ static void udf_close_lvid(struct super_block *sb) | |||
1790 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); | 1787 | lvid->integrityType = cpu_to_le32(LVID_INTEGRITY_TYPE_CLOSE); |
1791 | 1788 | ||
1792 | lvid->descTag.descCRC = cpu_to_le16( | 1789 | lvid->descTag.descCRC = cpu_to_le16( |
1793 | crc_itu_t(0, (char *)lvid + sizeof(tag), | 1790 | crc_itu_t(0, (char *)lvid + sizeof(struct tag), |
1794 | le16_to_cpu(lvid->descTag.descCRCLength))); | 1791 | le16_to_cpu(lvid->descTag.descCRCLength))); |
1795 | 1792 | ||
1796 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); | 1793 | lvid->descTag.tagChecksum = udf_tag_checksum(&lvid->descTag); |
1797 | mark_buffer_dirty(bh); | 1794 | mark_buffer_dirty(bh); |
1795 | sbi->s_lvid_dirty = 0; | ||
1798 | } | 1796 | } |
1799 | 1797 | ||
1800 | static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) | 1798 | static void udf_sb_free_bitmap(struct udf_bitmap *bitmap) |
@@ -1846,15 +1844,18 @@ static void udf_free_partition(struct udf_part_map *map) | |||
1846 | static int udf_fill_super(struct super_block *sb, void *options, int silent) | 1844 | static int udf_fill_super(struct super_block *sb, void *options, int silent) |
1847 | { | 1845 | { |
1848 | int i; | 1846 | int i; |
1847 | int ret; | ||
1849 | struct inode *inode = NULL; | 1848 | struct inode *inode = NULL; |
1850 | struct udf_options uopt; | 1849 | struct udf_options uopt; |
1851 | kernel_lb_addr rootdir, fileset; | 1850 | struct kernel_lb_addr rootdir, fileset; |
1852 | struct udf_sb_info *sbi; | 1851 | struct udf_sb_info *sbi; |
1853 | 1852 | ||
1854 | uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); | 1853 | uopt.flags = (1 << UDF_FLAG_USE_AD_IN_ICB) | (1 << UDF_FLAG_STRICT); |
1855 | uopt.uid = -1; | 1854 | uopt.uid = -1; |
1856 | uopt.gid = -1; | 1855 | uopt.gid = -1; |
1857 | uopt.umask = 0; | 1856 | uopt.umask = 0; |
1857 | uopt.fmode = UDF_INVALID_MODE; | ||
1858 | uopt.dmode = UDF_INVALID_MODE; | ||
1858 | 1859 | ||
1859 | sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); | 1860 | sbi = kzalloc(sizeof(struct udf_sb_info), GFP_KERNEL); |
1860 | if (!sbi) | 1861 | if (!sbi) |
@@ -1892,15 +1893,10 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1892 | sbi->s_uid = uopt.uid; | 1893 | sbi->s_uid = uopt.uid; |
1893 | sbi->s_gid = uopt.gid; | 1894 | sbi->s_gid = uopt.gid; |
1894 | sbi->s_umask = uopt.umask; | 1895 | sbi->s_umask = uopt.umask; |
1896 | sbi->s_fmode = uopt.fmode; | ||
1897 | sbi->s_dmode = uopt.dmode; | ||
1895 | sbi->s_nls_map = uopt.nls_map; | 1898 | sbi->s_nls_map = uopt.nls_map; |
1896 | 1899 | ||
1897 | /* Set the block size for all transfers */ | ||
1898 | if (!sb_min_blocksize(sb, uopt.blocksize)) { | ||
1899 | udf_debug("Bad block size (%d)\n", uopt.blocksize); | ||
1900 | printk(KERN_ERR "udf: bad block size (%d)\n", uopt.blocksize); | ||
1901 | goto error_out; | ||
1902 | } | ||
1903 | |||
1904 | if (uopt.session == 0xFFFFFFFF) | 1900 | if (uopt.session == 0xFFFFFFFF) |
1905 | sbi->s_session = udf_get_last_session(sb); | 1901 | sbi->s_session = udf_get_last_session(sb); |
1906 | else | 1902 | else |
@@ -1908,18 +1904,6 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1908 | 1904 | ||
1909 | udf_debug("Multi-session=%d\n", sbi->s_session); | 1905 | udf_debug("Multi-session=%d\n", sbi->s_session); |
1910 | 1906 | ||
1911 | sbi->s_last_block = uopt.lastblock; | ||
1912 | sbi->s_anchor[0] = sbi->s_anchor[1] = 0; | ||
1913 | sbi->s_anchor[2] = uopt.anchor; | ||
1914 | |||
1915 | if (udf_check_valid(sb, uopt.novrs, silent)) { | ||
1916 | /* read volume recognition sequences */ | ||
1917 | printk(KERN_WARNING "UDF-fs: No VRS found\n"); | ||
1918 | goto error_out; | ||
1919 | } | ||
1920 | |||
1921 | udf_find_anchor(sb); | ||
1922 | |||
1923 | /* Fill in the rest of the superblock */ | 1907 | /* Fill in the rest of the superblock */ |
1924 | sb->s_op = &udf_sb_ops; | 1908 | sb->s_op = &udf_sb_ops; |
1925 | sb->s_export_op = &udf_export_ops; | 1909 | sb->s_export_op = &udf_export_ops; |
@@ -1928,7 +1912,21 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1928 | sb->s_magic = UDF_SUPER_MAGIC; | 1912 | sb->s_magic = UDF_SUPER_MAGIC; |
1929 | sb->s_time_gran = 1000; | 1913 | sb->s_time_gran = 1000; |
1930 | 1914 | ||
1931 | if (udf_load_sequence(sb, &fileset)) { | 1915 | if (uopt.flags & (1 << UDF_FLAG_BLOCKSIZE_SET)) { |
1916 | ret = udf_load_vrs(sb, &uopt, silent, &fileset); | ||
1917 | } else { | ||
1918 | uopt.blocksize = bdev_hardsect_size(sb->s_bdev); | ||
1919 | ret = udf_load_vrs(sb, &uopt, silent, &fileset); | ||
1920 | if (!ret && uopt.blocksize != UDF_DEFAULT_BLOCKSIZE) { | ||
1921 | if (!silent) | ||
1922 | printk(KERN_NOTICE | ||
1923 | "UDF-fs: Rescanning with blocksize " | ||
1924 | "%d\n", UDF_DEFAULT_BLOCKSIZE); | ||
1925 | uopt.blocksize = UDF_DEFAULT_BLOCKSIZE; | ||
1926 | ret = udf_load_vrs(sb, &uopt, silent, &fileset); | ||
1927 | } | ||
1928 | } | ||
1929 | if (!ret) { | ||
1932 | printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); | 1930 | printk(KERN_WARNING "UDF-fs: No partition found (1)\n"); |
1933 | goto error_out; | 1931 | goto error_out; |
1934 | } | 1932 | } |
@@ -1978,7 +1976,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1978 | } | 1976 | } |
1979 | 1977 | ||
1980 | if (!silent) { | 1978 | if (!silent) { |
1981 | timestamp ts; | 1979 | struct timestamp ts; |
1982 | udf_time_to_disk_stamp(&ts, sbi->s_record_time); | 1980 | udf_time_to_disk_stamp(&ts, sbi->s_record_time); |
1983 | udf_info("UDF: Mounting volume '%s', " | 1981 | udf_info("UDF: Mounting volume '%s', " |
1984 | "timestamp %04u/%02u/%02u %02u:%02u (%x)\n", | 1982 | "timestamp %04u/%02u/%02u %02u:%02u (%x)\n", |
@@ -1991,7 +1989,7 @@ static int udf_fill_super(struct super_block *sb, void *options, int silent) | |||
1991 | /* Assign the root inode */ | 1989 | /* Assign the root inode */ |
1992 | /* assign inodes by physical block number */ | 1990 | /* assign inodes by physical block number */ |
1993 | /* perhaps it's not extensible enough, but for now ... */ | 1991 | /* perhaps it's not extensible enough, but for now ... */ |
1994 | inode = udf_iget(sb, rootdir); | 1992 | inode = udf_iget(sb, &rootdir); |
1995 | if (!inode) { | 1993 | if (!inode) { |
1996 | printk(KERN_ERR "UDF-fs: Error in udf_iget, block=%d, " | 1994 | printk(KERN_ERR "UDF-fs: Error in udf_iget, block=%d, " |
1997 | "partition=%d\n", | 1995 | "partition=%d\n", |
@@ -2081,11 +2079,31 @@ static void udf_put_super(struct super_block *sb) | |||
2081 | sb->s_fs_info = NULL; | 2079 | sb->s_fs_info = NULL; |
2082 | } | 2080 | } |
2083 | 2081 | ||
2082 | static int udf_sync_fs(struct super_block *sb, int wait) | ||
2083 | { | ||
2084 | struct udf_sb_info *sbi = UDF_SB(sb); | ||
2085 | |||
2086 | mutex_lock(&sbi->s_alloc_mutex); | ||
2087 | if (sbi->s_lvid_dirty) { | ||
2088 | /* | ||
2089 | * Blockdevice will be synced later so we don't have to submit | ||
2090 | * the buffer for IO | ||
2091 | */ | ||
2092 | mark_buffer_dirty(sbi->s_lvid_bh); | ||
2093 | sb->s_dirt = 0; | ||
2094 | sbi->s_lvid_dirty = 0; | ||
2095 | } | ||
2096 | mutex_unlock(&sbi->s_alloc_mutex); | ||
2097 | |||
2098 | return 0; | ||
2099 | } | ||
2100 | |||
2084 | static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) | 2101 | static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) |
2085 | { | 2102 | { |
2086 | struct super_block *sb = dentry->d_sb; | 2103 | struct super_block *sb = dentry->d_sb; |
2087 | struct udf_sb_info *sbi = UDF_SB(sb); | 2104 | struct udf_sb_info *sbi = UDF_SB(sb); |
2088 | struct logicalVolIntegrityDescImpUse *lvidiu; | 2105 | struct logicalVolIntegrityDescImpUse *lvidiu; |
2106 | u64 id = huge_encode_dev(sb->s_bdev->bd_dev); | ||
2089 | 2107 | ||
2090 | if (sbi->s_lvid_bh != NULL) | 2108 | if (sbi->s_lvid_bh != NULL) |
2091 | lvidiu = udf_sb_lvidiu(sbi); | 2109 | lvidiu = udf_sb_lvidiu(sbi); |
@@ -2101,8 +2119,9 @@ static int udf_statfs(struct dentry *dentry, struct kstatfs *buf) | |||
2101 | le32_to_cpu(lvidiu->numDirs)) : 0) | 2119 | le32_to_cpu(lvidiu->numDirs)) : 0) |
2102 | + buf->f_bfree; | 2120 | + buf->f_bfree; |
2103 | buf->f_ffree = buf->f_bfree; | 2121 | buf->f_ffree = buf->f_bfree; |
2104 | /* __kernel_fsid_t f_fsid */ | ||
2105 | buf->f_namelen = UDF_NAME_LEN - 2; | 2122 | buf->f_namelen = UDF_NAME_LEN - 2; |
2123 | buf->f_fsid.val[0] = (u32)id; | ||
2124 | buf->f_fsid.val[1] = (u32)(id >> 32); | ||
2106 | 2125 | ||
2107 | return 0; | 2126 | return 0; |
2108 | } | 2127 | } |
@@ -2114,7 +2133,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, | |||
2114 | unsigned int accum = 0; | 2133 | unsigned int accum = 0; |
2115 | int index; | 2134 | int index; |
2116 | int block = 0, newblock; | 2135 | int block = 0, newblock; |
2117 | kernel_lb_addr loc; | 2136 | struct kernel_lb_addr loc; |
2118 | uint32_t bytes; | 2137 | uint32_t bytes; |
2119 | uint8_t *ptr; | 2138 | uint8_t *ptr; |
2120 | uint16_t ident; | 2139 | uint16_t ident; |
@@ -2124,7 +2143,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, | |||
2124 | 2143 | ||
2125 | loc.logicalBlockNum = bitmap->s_extPosition; | 2144 | loc.logicalBlockNum = bitmap->s_extPosition; |
2126 | loc.partitionReferenceNum = UDF_SB(sb)->s_partition; | 2145 | loc.partitionReferenceNum = UDF_SB(sb)->s_partition; |
2127 | bh = udf_read_ptagged(sb, loc, 0, &ident); | 2146 | bh = udf_read_ptagged(sb, &loc, 0, &ident); |
2128 | 2147 | ||
2129 | if (!bh) { | 2148 | if (!bh) { |
2130 | printk(KERN_ERR "udf: udf_count_free failed\n"); | 2149 | printk(KERN_ERR "udf: udf_count_free failed\n"); |
@@ -2147,7 +2166,7 @@ static unsigned int udf_count_free_bitmap(struct super_block *sb, | |||
2147 | bytes -= cur_bytes; | 2166 | bytes -= cur_bytes; |
2148 | if (bytes) { | 2167 | if (bytes) { |
2149 | brelse(bh); | 2168 | brelse(bh); |
2150 | newblock = udf_get_lb_pblock(sb, loc, ++block); | 2169 | newblock = udf_get_lb_pblock(sb, &loc, ++block); |
2151 | bh = udf_tread(sb, newblock); | 2170 | bh = udf_tread(sb, newblock); |
2152 | if (!bh) { | 2171 | if (!bh) { |
2153 | udf_debug("read failed\n"); | 2172 | udf_debug("read failed\n"); |
@@ -2170,7 +2189,7 @@ static unsigned int udf_count_free_table(struct super_block *sb, | |||
2170 | { | 2189 | { |
2171 | unsigned int accum = 0; | 2190 | unsigned int accum = 0; |
2172 | uint32_t elen; | 2191 | uint32_t elen; |
2173 | kernel_lb_addr eloc; | 2192 | struct kernel_lb_addr eloc; |
2174 | int8_t etype; | 2193 | int8_t etype; |
2175 | struct extent_position epos; | 2194 | struct extent_position epos; |
2176 | 2195 | ||
diff --git a/fs/udf/truncate.c b/fs/udf/truncate.c index 65e19b4f9424..225527cdc885 100644 --- a/fs/udf/truncate.c +++ b/fs/udf/truncate.c | |||
@@ -28,10 +28,10 @@ | |||
28 | #include "udf_sb.h" | 28 | #include "udf_sb.h" |
29 | 29 | ||
30 | static void extent_trunc(struct inode *inode, struct extent_position *epos, | 30 | static void extent_trunc(struct inode *inode, struct extent_position *epos, |
31 | kernel_lb_addr eloc, int8_t etype, uint32_t elen, | 31 | struct kernel_lb_addr *eloc, int8_t etype, uint32_t elen, |
32 | uint32_t nelen) | 32 | uint32_t nelen) |
33 | { | 33 | { |
34 | kernel_lb_addr neloc = {}; | 34 | struct kernel_lb_addr neloc = {}; |
35 | int last_block = (elen + inode->i_sb->s_blocksize - 1) >> | 35 | int last_block = (elen + inode->i_sb->s_blocksize - 1) >> |
36 | inode->i_sb->s_blocksize_bits; | 36 | inode->i_sb->s_blocksize_bits; |
37 | int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> | 37 | int first_block = (nelen + inode->i_sb->s_blocksize - 1) >> |
@@ -43,12 +43,12 @@ static void extent_trunc(struct inode *inode, struct extent_position *epos, | |||
43 | last_block); | 43 | last_block); |
44 | etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30); | 44 | etype = (EXT_NOT_RECORDED_NOT_ALLOCATED >> 30); |
45 | } else | 45 | } else |
46 | neloc = eloc; | 46 | neloc = *eloc; |
47 | nelen = (etype << 30) | nelen; | 47 | nelen = (etype << 30) | nelen; |
48 | } | 48 | } |
49 | 49 | ||
50 | if (elen != nelen) { | 50 | if (elen != nelen) { |
51 | udf_write_aext(inode, epos, neloc, nelen, 0); | 51 | udf_write_aext(inode, epos, &neloc, nelen, 0); |
52 | if (last_block - first_block > 0) { | 52 | if (last_block - first_block > 0) { |
53 | if (etype == (EXT_RECORDED_ALLOCATED >> 30)) | 53 | if (etype == (EXT_RECORDED_ALLOCATED >> 30)) |
54 | mark_inode_dirty(inode); | 54 | mark_inode_dirty(inode); |
@@ -68,7 +68,7 @@ static void extent_trunc(struct inode *inode, struct extent_position *epos, | |||
68 | void udf_truncate_tail_extent(struct inode *inode) | 68 | void udf_truncate_tail_extent(struct inode *inode) |
69 | { | 69 | { |
70 | struct extent_position epos = {}; | 70 | struct extent_position epos = {}; |
71 | kernel_lb_addr eloc; | 71 | struct kernel_lb_addr eloc; |
72 | uint32_t elen, nelen; | 72 | uint32_t elen, nelen; |
73 | uint64_t lbcount = 0; | 73 | uint64_t lbcount = 0; |
74 | int8_t etype = -1, netype; | 74 | int8_t etype = -1, netype; |
@@ -83,9 +83,9 @@ void udf_truncate_tail_extent(struct inode *inode) | |||
83 | return; | 83 | return; |
84 | 84 | ||
85 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 85 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
86 | adsize = sizeof(short_ad); | 86 | adsize = sizeof(struct short_ad); |
87 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 87 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
88 | adsize = sizeof(long_ad); | 88 | adsize = sizeof(struct long_ad); |
89 | else | 89 | else |
90 | BUG(); | 90 | BUG(); |
91 | 91 | ||
@@ -106,7 +106,7 @@ void udf_truncate_tail_extent(struct inode *inode) | |||
106 | (unsigned)elen); | 106 | (unsigned)elen); |
107 | nelen = elen - (lbcount - inode->i_size); | 107 | nelen = elen - (lbcount - inode->i_size); |
108 | epos.offset -= adsize; | 108 | epos.offset -= adsize; |
109 | extent_trunc(inode, &epos, eloc, etype, elen, nelen); | 109 | extent_trunc(inode, &epos, &eloc, etype, elen, nelen); |
110 | epos.offset += adsize; | 110 | epos.offset += adsize; |
111 | if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) | 111 | if (udf_next_aext(inode, &epos, &eloc, &elen, 1) != -1) |
112 | printk(KERN_ERR "udf_truncate_tail_extent(): " | 112 | printk(KERN_ERR "udf_truncate_tail_extent(): " |
@@ -124,7 +124,7 @@ void udf_truncate_tail_extent(struct inode *inode) | |||
124 | void udf_discard_prealloc(struct inode *inode) | 124 | void udf_discard_prealloc(struct inode *inode) |
125 | { | 125 | { |
126 | struct extent_position epos = { NULL, 0, {0, 0} }; | 126 | struct extent_position epos = { NULL, 0, {0, 0} }; |
127 | kernel_lb_addr eloc; | 127 | struct kernel_lb_addr eloc; |
128 | uint32_t elen; | 128 | uint32_t elen; |
129 | uint64_t lbcount = 0; | 129 | uint64_t lbcount = 0; |
130 | int8_t etype = -1, netype; | 130 | int8_t etype = -1, netype; |
@@ -136,9 +136,9 @@ void udf_discard_prealloc(struct inode *inode) | |||
136 | return; | 136 | return; |
137 | 137 | ||
138 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 138 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
139 | adsize = sizeof(short_ad); | 139 | adsize = sizeof(struct short_ad); |
140 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 140 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
141 | adsize = sizeof(long_ad); | 141 | adsize = sizeof(struct long_ad); |
142 | else | 142 | else |
143 | adsize = 0; | 143 | adsize = 0; |
144 | 144 | ||
@@ -152,7 +152,7 @@ void udf_discard_prealloc(struct inode *inode) | |||
152 | if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { | 152 | if (etype == (EXT_NOT_RECORDED_ALLOCATED >> 30)) { |
153 | epos.offset -= adsize; | 153 | epos.offset -= adsize; |
154 | lbcount -= elen; | 154 | lbcount -= elen; |
155 | extent_trunc(inode, &epos, eloc, etype, elen, 0); | 155 | extent_trunc(inode, &epos, &eloc, etype, elen, 0); |
156 | if (!epos.bh) { | 156 | if (!epos.bh) { |
157 | iinfo->i_lenAlloc = | 157 | iinfo->i_lenAlloc = |
158 | epos.offset - | 158 | epos.offset - |
@@ -200,7 +200,7 @@ static void udf_update_alloc_ext_desc(struct inode *inode, | |||
200 | void udf_truncate_extents(struct inode *inode) | 200 | void udf_truncate_extents(struct inode *inode) |
201 | { | 201 | { |
202 | struct extent_position epos; | 202 | struct extent_position epos; |
203 | kernel_lb_addr eloc, neloc = {}; | 203 | struct kernel_lb_addr eloc, neloc = {}; |
204 | uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; | 204 | uint32_t elen, nelen = 0, indirect_ext_len = 0, lenalloc; |
205 | int8_t etype; | 205 | int8_t etype; |
206 | struct super_block *sb = inode->i_sb; | 206 | struct super_block *sb = inode->i_sb; |
@@ -210,9 +210,9 @@ void udf_truncate_extents(struct inode *inode) | |||
210 | struct udf_inode_info *iinfo = UDF_I(inode); | 210 | struct udf_inode_info *iinfo = UDF_I(inode); |
211 | 211 | ||
212 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) | 212 | if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_SHORT) |
213 | adsize = sizeof(short_ad); | 213 | adsize = sizeof(struct short_ad); |
214 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) | 214 | else if (iinfo->i_alloc_type == ICBTAG_FLAG_AD_LONG) |
215 | adsize = sizeof(long_ad); | 215 | adsize = sizeof(struct long_ad); |
216 | else | 216 | else |
217 | BUG(); | 217 | BUG(); |
218 | 218 | ||
@@ -221,7 +221,7 @@ void udf_truncate_extents(struct inode *inode) | |||
221 | (inode->i_size & (sb->s_blocksize - 1)); | 221 | (inode->i_size & (sb->s_blocksize - 1)); |
222 | if (etype != -1) { | 222 | if (etype != -1) { |
223 | epos.offset -= adsize; | 223 | epos.offset -= adsize; |
224 | extent_trunc(inode, &epos, eloc, etype, elen, byte_offset); | 224 | extent_trunc(inode, &epos, &eloc, etype, elen, byte_offset); |
225 | epos.offset += adsize; | 225 | epos.offset += adsize; |
226 | if (byte_offset) | 226 | if (byte_offset) |
227 | lenalloc = epos.offset; | 227 | lenalloc = epos.offset; |
@@ -236,12 +236,12 @@ void udf_truncate_extents(struct inode *inode) | |||
236 | while ((etype = udf_current_aext(inode, &epos, &eloc, | 236 | while ((etype = udf_current_aext(inode, &epos, &eloc, |
237 | &elen, 0)) != -1) { | 237 | &elen, 0)) != -1) { |
238 | if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { | 238 | if (etype == (EXT_NEXT_EXTENT_ALLOCDECS >> 30)) { |
239 | udf_write_aext(inode, &epos, neloc, nelen, 0); | 239 | udf_write_aext(inode, &epos, &neloc, nelen, 0); |
240 | if (indirect_ext_len) { | 240 | if (indirect_ext_len) { |
241 | /* We managed to free all extents in the | 241 | /* We managed to free all extents in the |
242 | * indirect extent - free it too */ | 242 | * indirect extent - free it too */ |
243 | BUG_ON(!epos.bh); | 243 | BUG_ON(!epos.bh); |
244 | udf_free_blocks(sb, inode, epos.block, | 244 | udf_free_blocks(sb, inode, &epos.block, |
245 | 0, indirect_ext_len); | 245 | 0, indirect_ext_len); |
246 | } else if (!epos.bh) { | 246 | } else if (!epos.bh) { |
247 | iinfo->i_lenAlloc = lenalloc; | 247 | iinfo->i_lenAlloc = lenalloc; |
@@ -253,7 +253,7 @@ void udf_truncate_extents(struct inode *inode) | |||
253 | epos.offset = sizeof(struct allocExtDesc); | 253 | epos.offset = sizeof(struct allocExtDesc); |
254 | epos.block = eloc; | 254 | epos.block = eloc; |
255 | epos.bh = udf_tread(sb, | 255 | epos.bh = udf_tread(sb, |
256 | udf_get_lb_pblock(sb, eloc, 0)); | 256 | udf_get_lb_pblock(sb, &eloc, 0)); |
257 | if (elen) | 257 | if (elen) |
258 | indirect_ext_len = | 258 | indirect_ext_len = |
259 | (elen + sb->s_blocksize - 1) >> | 259 | (elen + sb->s_blocksize - 1) >> |
@@ -261,7 +261,7 @@ void udf_truncate_extents(struct inode *inode) | |||
261 | else | 261 | else |
262 | indirect_ext_len = 1; | 262 | indirect_ext_len = 1; |
263 | } else { | 263 | } else { |
264 | extent_trunc(inode, &epos, eloc, etype, | 264 | extent_trunc(inode, &epos, &eloc, etype, |
265 | elen, 0); | 265 | elen, 0); |
266 | epos.offset += adsize; | 266 | epos.offset += adsize; |
267 | } | 267 | } |
@@ -269,7 +269,7 @@ void udf_truncate_extents(struct inode *inode) | |||
269 | 269 | ||
270 | if (indirect_ext_len) { | 270 | if (indirect_ext_len) { |
271 | BUG_ON(!epos.bh); | 271 | BUG_ON(!epos.bh); |
272 | udf_free_blocks(sb, inode, epos.block, 0, | 272 | udf_free_blocks(sb, inode, &epos.block, 0, |
273 | indirect_ext_len); | 273 | indirect_ext_len); |
274 | } else if (!epos.bh) { | 274 | } else if (!epos.bh) { |
275 | iinfo->i_lenAlloc = lenalloc; | 275 | iinfo->i_lenAlloc = lenalloc; |
@@ -278,7 +278,7 @@ void udf_truncate_extents(struct inode *inode) | |||
278 | udf_update_alloc_ext_desc(inode, &epos, lenalloc); | 278 | udf_update_alloc_ext_desc(inode, &epos, lenalloc); |
279 | } else if (inode->i_size) { | 279 | } else if (inode->i_size) { |
280 | if (byte_offset) { | 280 | if (byte_offset) { |
281 | kernel_long_ad extent; | 281 | struct kernel_long_ad extent; |
282 | 282 | ||
283 | /* | 283 | /* |
284 | * OK, there is not extent covering inode->i_size and | 284 | * OK, there is not extent covering inode->i_size and |
diff --git a/fs/udf/udf_i.h b/fs/udf/udf_i.h index 4f86b1d98a5d..e58d1de41073 100644 --- a/fs/udf/udf_i.h +++ b/fs/udf/udf_i.h | |||
@@ -4,7 +4,7 @@ | |||
4 | struct udf_inode_info { | 4 | struct udf_inode_info { |
5 | struct timespec i_crtime; | 5 | struct timespec i_crtime; |
6 | /* Physical address of inode */ | 6 | /* Physical address of inode */ |
7 | kernel_lb_addr i_location; | 7 | struct kernel_lb_addr i_location; |
8 | __u64 i_unique; | 8 | __u64 i_unique; |
9 | __u32 i_lenEAttr; | 9 | __u32 i_lenEAttr; |
10 | __u32 i_lenAlloc; | 10 | __u32 i_lenAlloc; |
@@ -17,8 +17,8 @@ struct udf_inode_info { | |||
17 | unsigned i_strat4096 : 1; | 17 | unsigned i_strat4096 : 1; |
18 | unsigned reserved : 26; | 18 | unsigned reserved : 26; |
19 | union { | 19 | union { |
20 | short_ad *i_sad; | 20 | struct short_ad *i_sad; |
21 | long_ad *i_lad; | 21 | struct long_ad *i_lad; |
22 | __u8 *i_data; | 22 | __u8 *i_data; |
23 | } i_ext; | 23 | } i_ext; |
24 | struct inode vfs_inode; | 24 | struct inode vfs_inode; |
diff --git a/fs/udf/udf_sb.h b/fs/udf/udf_sb.h index 1c1c514a9725..d113b72c2768 100644 --- a/fs/udf/udf_sb.h +++ b/fs/udf/udf_sb.h | |||
@@ -30,6 +30,7 @@ | |||
30 | #define UDF_FLAG_GID_SET 16 | 30 | #define UDF_FLAG_GID_SET 16 |
31 | #define UDF_FLAG_SESSION_SET 17 | 31 | #define UDF_FLAG_SESSION_SET 17 |
32 | #define UDF_FLAG_LASTBLOCK_SET 18 | 32 | #define UDF_FLAG_LASTBLOCK_SET 18 |
33 | #define UDF_FLAG_BLOCKSIZE_SET 19 | ||
33 | 34 | ||
34 | #define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 | 35 | #define UDF_PART_FLAG_UNALLOC_BITMAP 0x0001 |
35 | #define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 | 36 | #define UDF_PART_FLAG_UNALLOC_TABLE 0x0002 |
@@ -48,6 +49,8 @@ | |||
48 | #define UDF_SPARABLE_MAP15 0x1522U | 49 | #define UDF_SPARABLE_MAP15 0x1522U |
49 | #define UDF_METADATA_MAP25 0x2511U | 50 | #define UDF_METADATA_MAP25 0x2511U |
50 | 51 | ||
52 | #define UDF_INVALID_MODE ((mode_t)-1) | ||
53 | |||
51 | #pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */ | 54 | #pragma pack(1) /* XXX(hch): Why? This file just defines in-core structures */ |
52 | 55 | ||
53 | struct udf_meta_data { | 56 | struct udf_meta_data { |
@@ -114,7 +117,7 @@ struct udf_sb_info { | |||
114 | 117 | ||
115 | /* Sector headers */ | 118 | /* Sector headers */ |
116 | __s32 s_session; | 119 | __s32 s_session; |
117 | __u32 s_anchor[3]; | 120 | __u32 s_anchor; |
118 | __u32 s_last_block; | 121 | __u32 s_last_block; |
119 | 122 | ||
120 | struct buffer_head *s_lvid_bh; | 123 | struct buffer_head *s_lvid_bh; |
@@ -123,6 +126,8 @@ struct udf_sb_info { | |||
123 | mode_t s_umask; | 126 | mode_t s_umask; |
124 | gid_t s_gid; | 127 | gid_t s_gid; |
125 | uid_t s_uid; | 128 | uid_t s_uid; |
129 | mode_t s_fmode; | ||
130 | mode_t s_dmode; | ||
126 | 131 | ||
127 | /* Root Info */ | 132 | /* Root Info */ |
128 | struct timespec s_record_time; | 133 | struct timespec s_record_time; |
@@ -143,6 +148,8 @@ struct udf_sb_info { | |||
143 | struct inode *s_vat_inode; | 148 | struct inode *s_vat_inode; |
144 | 149 | ||
145 | struct mutex s_alloc_mutex; | 150 | struct mutex s_alloc_mutex; |
151 | /* Protected by s_alloc_mutex */ | ||
152 | unsigned int s_lvid_dirty; | ||
146 | }; | 153 | }; |
147 | 154 | ||
148 | static inline struct udf_sb_info *UDF_SB(struct super_block *sb) | 155 | static inline struct udf_sb_info *UDF_SB(struct super_block *sb) |
diff --git a/fs/udf/udfdecl.h b/fs/udf/udfdecl.h index 8ec865de5f13..cac51b77a5d1 100644 --- a/fs/udf/udfdecl.h +++ b/fs/udf/udfdecl.h | |||
@@ -62,10 +62,8 @@ static inline size_t udf_ext0_offset(struct inode *inode) | |||
62 | return 0; | 62 | return 0; |
63 | } | 63 | } |
64 | 64 | ||
65 | #define udf_get_lb_pblock(sb,loc,offset) udf_get_pblock((sb), (loc).logicalBlockNum, (loc).partitionReferenceNum, (offset)) | ||
66 | |||
67 | /* computes tag checksum */ | 65 | /* computes tag checksum */ |
68 | u8 udf_tag_checksum(const tag *t); | 66 | u8 udf_tag_checksum(const struct tag *t); |
69 | 67 | ||
70 | struct dentry; | 68 | struct dentry; |
71 | struct inode; | 69 | struct inode; |
@@ -95,7 +93,7 @@ struct udf_vds_record { | |||
95 | }; | 93 | }; |
96 | 94 | ||
97 | struct generic_desc { | 95 | struct generic_desc { |
98 | tag descTag; | 96 | struct tag descTag; |
99 | __le32 volDescSeqNum; | 97 | __le32 volDescSeqNum; |
100 | }; | 98 | }; |
101 | 99 | ||
@@ -108,11 +106,22 @@ struct ustr { | |||
108 | struct extent_position { | 106 | struct extent_position { |
109 | struct buffer_head *bh; | 107 | struct buffer_head *bh; |
110 | uint32_t offset; | 108 | uint32_t offset; |
111 | kernel_lb_addr block; | 109 | struct kernel_lb_addr block; |
112 | }; | 110 | }; |
113 | 111 | ||
114 | /* super.c */ | 112 | /* super.c */ |
115 | extern void udf_warning(struct super_block *, const char *, const char *, ...); | 113 | extern void udf_warning(struct super_block *, const char *, const char *, ...); |
114 | static inline void udf_updated_lvid(struct super_block *sb) | ||
115 | { | ||
116 | struct buffer_head *bh = UDF_SB(sb)->s_lvid_bh; | ||
117 | |||
118 | BUG_ON(!bh); | ||
119 | WARN_ON_ONCE(((struct logicalVolIntegrityDesc *) | ||
120 | bh->b_data)->integrityType != | ||
121 | cpu_to_le32(LVID_INTEGRITY_TYPE_OPEN)); | ||
122 | sb->s_dirt = 1; | ||
123 | UDF_SB(sb)->s_lvid_dirty = 1; | ||
124 | } | ||
116 | 125 | ||
117 | /* namei.c */ | 126 | /* namei.c */ |
118 | extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, | 127 | extern int udf_write_fi(struct inode *inode, struct fileIdentDesc *, |
@@ -124,7 +133,7 @@ extern int udf_ioctl(struct inode *, struct file *, unsigned int, | |||
124 | unsigned long); | 133 | unsigned long); |
125 | 134 | ||
126 | /* inode.c */ | 135 | /* inode.c */ |
127 | extern struct inode *udf_iget(struct super_block *, kernel_lb_addr); | 136 | extern struct inode *udf_iget(struct super_block *, struct kernel_lb_addr *); |
128 | extern int udf_sync_inode(struct inode *); | 137 | extern int udf_sync_inode(struct inode *); |
129 | extern void udf_expand_file_adinicb(struct inode *, int, int *); | 138 | extern void udf_expand_file_adinicb(struct inode *, int, int *); |
130 | extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); | 139 | extern struct buffer_head *udf_expand_dir_adinicb(struct inode *, int *, int *); |
@@ -136,19 +145,19 @@ extern void udf_clear_inode(struct inode *); | |||
136 | extern int udf_write_inode(struct inode *, int); | 145 | extern int udf_write_inode(struct inode *, int); |
137 | extern long udf_block_map(struct inode *, sector_t); | 146 | extern long udf_block_map(struct inode *, sector_t); |
138 | extern int udf_extend_file(struct inode *, struct extent_position *, | 147 | extern int udf_extend_file(struct inode *, struct extent_position *, |
139 | kernel_long_ad *, sector_t); | 148 | struct kernel_long_ad *, sector_t); |
140 | extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, | 149 | extern int8_t inode_bmap(struct inode *, sector_t, struct extent_position *, |
141 | kernel_lb_addr *, uint32_t *, sector_t *); | 150 | struct kernel_lb_addr *, uint32_t *, sector_t *); |
142 | extern int8_t udf_add_aext(struct inode *, struct extent_position *, | 151 | extern int8_t udf_add_aext(struct inode *, struct extent_position *, |
143 | kernel_lb_addr, uint32_t, int); | 152 | struct kernel_lb_addr *, uint32_t, int); |
144 | extern int8_t udf_write_aext(struct inode *, struct extent_position *, | 153 | extern int8_t udf_write_aext(struct inode *, struct extent_position *, |
145 | kernel_lb_addr, uint32_t, int); | 154 | struct kernel_lb_addr *, uint32_t, int); |
146 | extern int8_t udf_delete_aext(struct inode *, struct extent_position, | 155 | extern int8_t udf_delete_aext(struct inode *, struct extent_position, |
147 | kernel_lb_addr, uint32_t); | 156 | struct kernel_lb_addr, uint32_t); |
148 | extern int8_t udf_next_aext(struct inode *, struct extent_position *, | 157 | extern int8_t udf_next_aext(struct inode *, struct extent_position *, |
149 | kernel_lb_addr *, uint32_t *, int); | 158 | struct kernel_lb_addr *, uint32_t *, int); |
150 | extern int8_t udf_current_aext(struct inode *, struct extent_position *, | 159 | extern int8_t udf_current_aext(struct inode *, struct extent_position *, |
151 | kernel_lb_addr *, uint32_t *, int); | 160 | struct kernel_lb_addr *, uint32_t *, int); |
152 | 161 | ||
153 | /* misc.c */ | 162 | /* misc.c */ |
154 | extern struct buffer_head *udf_tgetblk(struct super_block *, int); | 163 | extern struct buffer_head *udf_tgetblk(struct super_block *, int); |
@@ -160,7 +169,7 @@ extern struct genericFormat *udf_get_extendedattr(struct inode *, uint32_t, | |||
160 | extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, | 169 | extern struct buffer_head *udf_read_tagged(struct super_block *, uint32_t, |
161 | uint32_t, uint16_t *); | 170 | uint32_t, uint16_t *); |
162 | extern struct buffer_head *udf_read_ptagged(struct super_block *, | 171 | extern struct buffer_head *udf_read_ptagged(struct super_block *, |
163 | kernel_lb_addr, uint32_t, | 172 | struct kernel_lb_addr *, uint32_t, |
164 | uint16_t *); | 173 | uint16_t *); |
165 | extern void udf_update_tag(char *, int); | 174 | extern void udf_update_tag(char *, int); |
166 | extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int); | 175 | extern void udf_new_tag(char *, uint16_t, uint16_t, uint16_t, uint32_t, int); |
@@ -182,6 +191,14 @@ extern uint32_t udf_get_pblock_meta25(struct super_block *, uint32_t, uint16_t, | |||
182 | uint32_t); | 191 | uint32_t); |
183 | extern int udf_relocate_blocks(struct super_block *, long, long *); | 192 | extern int udf_relocate_blocks(struct super_block *, long, long *); |
184 | 193 | ||
194 | static inline uint32_t | ||
195 | udf_get_lb_pblock(struct super_block *sb, struct kernel_lb_addr *loc, | ||
196 | uint32_t offset) | ||
197 | { | ||
198 | return udf_get_pblock(sb, loc->logicalBlockNum, | ||
199 | loc->partitionReferenceNum, offset); | ||
200 | } | ||
201 | |||
185 | /* unicode.c */ | 202 | /* unicode.c */ |
186 | extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); | 203 | extern int udf_get_filename(struct super_block *, uint8_t *, uint8_t *, int); |
187 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, | 204 | extern int udf_put_filename(struct super_block *, const uint8_t *, uint8_t *, |
@@ -200,7 +217,7 @@ extern void udf_truncate_extents(struct inode *); | |||
200 | 217 | ||
201 | /* balloc.c */ | 218 | /* balloc.c */ |
202 | extern void udf_free_blocks(struct super_block *, struct inode *, | 219 | extern void udf_free_blocks(struct super_block *, struct inode *, |
203 | kernel_lb_addr, uint32_t, uint32_t); | 220 | struct kernel_lb_addr *, uint32_t, uint32_t); |
204 | extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, | 221 | extern int udf_prealloc_blocks(struct super_block *, struct inode *, uint16_t, |
205 | uint32_t, uint32_t); | 222 | uint32_t, uint32_t); |
206 | extern int udf_new_block(struct super_block *, struct inode *, uint16_t, | 223 | extern int udf_new_block(struct super_block *, struct inode *, uint16_t, |
@@ -214,16 +231,16 @@ extern struct fileIdentDesc *udf_fileident_read(struct inode *, loff_t *, | |||
214 | struct udf_fileident_bh *, | 231 | struct udf_fileident_bh *, |
215 | struct fileIdentDesc *, | 232 | struct fileIdentDesc *, |
216 | struct extent_position *, | 233 | struct extent_position *, |
217 | kernel_lb_addr *, uint32_t *, | 234 | struct kernel_lb_addr *, uint32_t *, |
218 | sector_t *); | 235 | sector_t *); |
219 | extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, | 236 | extern struct fileIdentDesc *udf_get_fileident(void *buffer, int bufsize, |
220 | int *offset); | 237 | int *offset); |
221 | extern long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); | 238 | extern struct long_ad *udf_get_filelongad(uint8_t *, int, uint32_t *, int); |
222 | extern short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); | 239 | extern struct short_ad *udf_get_fileshortad(uint8_t *, int, uint32_t *, int); |
223 | 240 | ||
224 | /* udftime.c */ | 241 | /* udftime.c */ |
225 | extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest, | 242 | extern struct timespec *udf_disk_stamp_to_time(struct timespec *dest, |
226 | timestamp src); | 243 | struct timestamp src); |
227 | extern timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec src); | 244 | extern struct timestamp *udf_time_to_disk_stamp(struct timestamp *dest, struct timespec src); |
228 | 245 | ||
229 | #endif /* __UDF_DECL_H */ | 246 | #endif /* __UDF_DECL_H */ |
diff --git a/fs/udf/udfend.h b/fs/udf/udfend.h index 489f52fb428c..6a9f3a9cc428 100644 --- a/fs/udf/udfend.h +++ b/fs/udf/udfend.h | |||
@@ -4,9 +4,9 @@ | |||
4 | #include <asm/byteorder.h> | 4 | #include <asm/byteorder.h> |
5 | #include <linux/string.h> | 5 | #include <linux/string.h> |
6 | 6 | ||
7 | static inline kernel_lb_addr lelb_to_cpu(lb_addr in) | 7 | static inline struct kernel_lb_addr lelb_to_cpu(struct lb_addr in) |
8 | { | 8 | { |
9 | kernel_lb_addr out; | 9 | struct kernel_lb_addr out; |
10 | 10 | ||
11 | out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum); | 11 | out.logicalBlockNum = le32_to_cpu(in.logicalBlockNum); |
12 | out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum); | 12 | out.partitionReferenceNum = le16_to_cpu(in.partitionReferenceNum); |
@@ -14,9 +14,9 @@ static inline kernel_lb_addr lelb_to_cpu(lb_addr in) | |||
14 | return out; | 14 | return out; |
15 | } | 15 | } |
16 | 16 | ||
17 | static inline lb_addr cpu_to_lelb(kernel_lb_addr in) | 17 | static inline struct lb_addr cpu_to_lelb(struct kernel_lb_addr in) |
18 | { | 18 | { |
19 | lb_addr out; | 19 | struct lb_addr out; |
20 | 20 | ||
21 | out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum); | 21 | out.logicalBlockNum = cpu_to_le32(in.logicalBlockNum); |
22 | out.partitionReferenceNum = cpu_to_le16(in.partitionReferenceNum); | 22 | out.partitionReferenceNum = cpu_to_le16(in.partitionReferenceNum); |
@@ -24,9 +24,9 @@ static inline lb_addr cpu_to_lelb(kernel_lb_addr in) | |||
24 | return out; | 24 | return out; |
25 | } | 25 | } |
26 | 26 | ||
27 | static inline short_ad lesa_to_cpu(short_ad in) | 27 | static inline struct short_ad lesa_to_cpu(struct short_ad in) |
28 | { | 28 | { |
29 | short_ad out; | 29 | struct short_ad out; |
30 | 30 | ||
31 | out.extLength = le32_to_cpu(in.extLength); | 31 | out.extLength = le32_to_cpu(in.extLength); |
32 | out.extPosition = le32_to_cpu(in.extPosition); | 32 | out.extPosition = le32_to_cpu(in.extPosition); |
@@ -34,9 +34,9 @@ static inline short_ad lesa_to_cpu(short_ad in) | |||
34 | return out; | 34 | return out; |
35 | } | 35 | } |
36 | 36 | ||
37 | static inline short_ad cpu_to_lesa(short_ad in) | 37 | static inline struct short_ad cpu_to_lesa(struct short_ad in) |
38 | { | 38 | { |
39 | short_ad out; | 39 | struct short_ad out; |
40 | 40 | ||
41 | out.extLength = cpu_to_le32(in.extLength); | 41 | out.extLength = cpu_to_le32(in.extLength); |
42 | out.extPosition = cpu_to_le32(in.extPosition); | 42 | out.extPosition = cpu_to_le32(in.extPosition); |
@@ -44,9 +44,9 @@ static inline short_ad cpu_to_lesa(short_ad in) | |||
44 | return out; | 44 | return out; |
45 | } | 45 | } |
46 | 46 | ||
47 | static inline kernel_long_ad lela_to_cpu(long_ad in) | 47 | static inline struct kernel_long_ad lela_to_cpu(struct long_ad in) |
48 | { | 48 | { |
49 | kernel_long_ad out; | 49 | struct kernel_long_ad out; |
50 | 50 | ||
51 | out.extLength = le32_to_cpu(in.extLength); | 51 | out.extLength = le32_to_cpu(in.extLength); |
52 | out.extLocation = lelb_to_cpu(in.extLocation); | 52 | out.extLocation = lelb_to_cpu(in.extLocation); |
@@ -54,9 +54,9 @@ static inline kernel_long_ad lela_to_cpu(long_ad in) | |||
54 | return out; | 54 | return out; |
55 | } | 55 | } |
56 | 56 | ||
57 | static inline long_ad cpu_to_lela(kernel_long_ad in) | 57 | static inline struct long_ad cpu_to_lela(struct kernel_long_ad in) |
58 | { | 58 | { |
59 | long_ad out; | 59 | struct long_ad out; |
60 | 60 | ||
61 | out.extLength = cpu_to_le32(in.extLength); | 61 | out.extLength = cpu_to_le32(in.extLength); |
62 | out.extLocation = cpu_to_lelb(in.extLocation); | 62 | out.extLocation = cpu_to_lelb(in.extLocation); |
@@ -64,9 +64,9 @@ static inline long_ad cpu_to_lela(kernel_long_ad in) | |||
64 | return out; | 64 | return out; |
65 | } | 65 | } |
66 | 66 | ||
67 | static inline kernel_extent_ad leea_to_cpu(extent_ad in) | 67 | static inline struct kernel_extent_ad leea_to_cpu(struct extent_ad in) |
68 | { | 68 | { |
69 | kernel_extent_ad out; | 69 | struct kernel_extent_ad out; |
70 | 70 | ||
71 | out.extLength = le32_to_cpu(in.extLength); | 71 | out.extLength = le32_to_cpu(in.extLength); |
72 | out.extLocation = le32_to_cpu(in.extLocation); | 72 | out.extLocation = le32_to_cpu(in.extLocation); |
diff --git a/fs/udf/udftime.c b/fs/udf/udftime.c index 5f811655c9b5..b8c828c4d200 100644 --- a/fs/udf/udftime.c +++ b/fs/udf/udftime.c | |||
@@ -85,7 +85,8 @@ extern struct timezone sys_tz; | |||
85 | #define SECS_PER_HOUR (60 * 60) | 85 | #define SECS_PER_HOUR (60 * 60) |
86 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) | 86 | #define SECS_PER_DAY (SECS_PER_HOUR * 24) |
87 | 87 | ||
88 | struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src) | 88 | struct timespec * |
89 | udf_disk_stamp_to_time(struct timespec *dest, struct timestamp src) | ||
89 | { | 90 | { |
90 | int yday; | 91 | int yday; |
91 | u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone); | 92 | u16 typeAndTimezone = le16_to_cpu(src.typeAndTimezone); |
@@ -116,7 +117,8 @@ struct timespec *udf_disk_stamp_to_time(struct timespec *dest, timestamp src) | |||
116 | return dest; | 117 | return dest; |
117 | } | 118 | } |
118 | 119 | ||
119 | timestamp *udf_time_to_disk_stamp(timestamp *dest, struct timespec ts) | 120 | struct timestamp * |
121 | udf_time_to_disk_stamp(struct timestamp *dest, struct timespec ts) | ||
120 | { | 122 | { |
121 | long int days, rem, y; | 123 | long int days, rem, y; |
122 | const unsigned short int *ip; | 124 | const unsigned short int *ip; |
diff --git a/fs/udf/unicode.c b/fs/udf/unicode.c index 9fdf8c93c58e..cefa8c8913e6 100644 --- a/fs/udf/unicode.c +++ b/fs/udf/unicode.c | |||
@@ -254,7 +254,7 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | |||
254 | { | 254 | { |
255 | const uint8_t *ocu; | 255 | const uint8_t *ocu; |
256 | uint8_t cmp_id, ocu_len; | 256 | uint8_t cmp_id, ocu_len; |
257 | int i; | 257 | int i, len; |
258 | 258 | ||
259 | 259 | ||
260 | ocu_len = ocu_i->u_len; | 260 | ocu_len = ocu_i->u_len; |
@@ -279,8 +279,13 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | |||
279 | if (cmp_id == 16) | 279 | if (cmp_id == 16) |
280 | c = (c << 8) | ocu[i++]; | 280 | c = (c << 8) | ocu[i++]; |
281 | 281 | ||
282 | utf_o->u_len += nls->uni2char(c, &utf_o->u_name[utf_o->u_len], | 282 | len = nls->uni2char(c, &utf_o->u_name[utf_o->u_len], |
283 | UDF_NAME_LEN - utf_o->u_len); | 283 | UDF_NAME_LEN - utf_o->u_len); |
284 | /* Valid character? */ | ||
285 | if (len >= 0) | ||
286 | utf_o->u_len += len; | ||
287 | else | ||
288 | utf_o->u_name[utf_o->u_len++] = '?'; | ||
284 | } | 289 | } |
285 | utf_o->u_cmpID = 8; | 290 | utf_o->u_cmpID = 8; |
286 | 291 | ||
@@ -290,7 +295,8 @@ static int udf_CS0toNLS(struct nls_table *nls, struct ustr *utf_o, | |||
290 | static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, | 295 | static int udf_NLStoCS0(struct nls_table *nls, dstring *ocu, struct ustr *uni, |
291 | int length) | 296 | int length) |
292 | { | 297 | { |
293 | unsigned len, i, max_val; | 298 | int len; |
299 | unsigned i, max_val; | ||
294 | uint16_t uni_char; | 300 | uint16_t uni_char; |
295 | int u_len; | 301 | int u_len; |
296 | 302 | ||
@@ -302,8 +308,13 @@ try_again: | |||
302 | u_len = 0U; | 308 | u_len = 0U; |
303 | for (i = 0U; i < uni->u_len; i++) { | 309 | for (i = 0U; i < uni->u_len; i++) { |
304 | len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char); | 310 | len = nls->char2uni(&uni->u_name[i], uni->u_len - i, &uni_char); |
305 | if (len <= 0) | 311 | if (!len) |
306 | continue; | 312 | continue; |
313 | /* Invalid character, deal with it */ | ||
314 | if (len < 0) { | ||
315 | len = 1; | ||
316 | uni_char = '?'; | ||
317 | } | ||
307 | 318 | ||
308 | if (uni_char > max_val) { | 319 | if (uni_char > max_val) { |
309 | max_val = 0xffffU; | 320 | max_val = 0xffffU; |
@@ -324,34 +335,43 @@ try_again: | |||
324 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, | 335 | int udf_get_filename(struct super_block *sb, uint8_t *sname, uint8_t *dname, |
325 | int flen) | 336 | int flen) |
326 | { | 337 | { |
327 | struct ustr filename, unifilename; | 338 | struct ustr *filename, *unifilename; |
328 | int len; | 339 | int len = 0; |
329 | 340 | ||
330 | if (udf_build_ustr_exact(&unifilename, sname, flen)) | 341 | filename = kmalloc(sizeof(struct ustr), GFP_NOFS); |
342 | if (!filename) | ||
331 | return 0; | 343 | return 0; |
332 | 344 | ||
345 | unifilename = kmalloc(sizeof(struct ustr), GFP_NOFS); | ||
346 | if (!unifilename) | ||
347 | goto out1; | ||
348 | |||
349 | if (udf_build_ustr_exact(unifilename, sname, flen)) | ||
350 | goto out2; | ||
351 | |||
333 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { | 352 | if (UDF_QUERY_FLAG(sb, UDF_FLAG_UTF8)) { |
334 | if (!udf_CS0toUTF8(&filename, &unifilename)) { | 353 | if (!udf_CS0toUTF8(filename, unifilename)) { |
335 | udf_debug("Failed in udf_get_filename: sname = %s\n", | 354 | udf_debug("Failed in udf_get_filename: sname = %s\n", |
336 | sname); | 355 | sname); |
337 | return 0; | 356 | goto out2; |
338 | } | 357 | } |
339 | } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { | 358 | } else if (UDF_QUERY_FLAG(sb, UDF_FLAG_NLS_MAP)) { |
340 | if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, &filename, | 359 | if (!udf_CS0toNLS(UDF_SB(sb)->s_nls_map, filename, |
341 | &unifilename)) { | 360 | unifilename)) { |
342 | udf_debug("Failed in udf_get_filename: sname = %s\n", | 361 | udf_debug("Failed in udf_get_filename: sname = %s\n", |
343 | sname); | 362 | sname); |
344 | return 0; | 363 | goto out2; |
345 | } | 364 | } |
346 | } else | 365 | } else |
347 | return 0; | 366 | goto out2; |
348 | 367 | ||
349 | len = udf_translate_to_linux(dname, filename.u_name, filename.u_len, | 368 | len = udf_translate_to_linux(dname, filename->u_name, filename->u_len, |
350 | unifilename.u_name, unifilename.u_len); | 369 | unifilename->u_name, unifilename->u_len); |
351 | if (len) | 370 | out2: |
352 | return len; | 371 | kfree(unifilename); |
353 | 372 | out1: | |
354 | return 0; | 373 | kfree(filename); |
374 | return len; | ||
355 | } | 375 | } |
356 | 376 | ||
357 | int udf_put_filename(struct super_block *sb, const uint8_t *sname, | 377 | int udf_put_filename(struct super_block *sb, const uint8_t *sname, |
diff --git a/fs/xfs/Makefile b/fs/xfs/Makefile index c3dc491fff89..60f107e47fe9 100644 --- a/fs/xfs/Makefile +++ b/fs/xfs/Makefile | |||
@@ -33,6 +33,7 @@ xfs-$(CONFIG_XFS_QUOTA) += $(addprefix quota/, \ | |||
33 | xfs_qm_syscalls.o \ | 33 | xfs_qm_syscalls.o \ |
34 | xfs_qm_bhv.o \ | 34 | xfs_qm_bhv.o \ |
35 | xfs_qm.o) | 35 | xfs_qm.o) |
36 | xfs-$(CONFIG_XFS_QUOTA) += linux-2.6/xfs_quotaops.o | ||
36 | 37 | ||
37 | ifeq ($(CONFIG_XFS_QUOTA),y) | 38 | ifeq ($(CONFIG_XFS_QUOTA),y) |
38 | xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o | 39 | xfs-$(CONFIG_PROC_FS) += quota/xfs_qm_stats.o |
diff --git a/fs/xfs/linux-2.6/mutex.h b/fs/xfs/linux-2.6/mutex.h deleted file mode 100644 index 2a88d56c4dc2..000000000000 --- a/fs/xfs/linux-2.6/mutex.h +++ /dev/null | |||
@@ -1,25 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2000-2003,2005 Silicon Graphics, Inc. | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #ifndef __XFS_SUPPORT_MUTEX_H__ | ||
19 | #define __XFS_SUPPORT_MUTEX_H__ | ||
20 | |||
21 | #include <linux/mutex.h> | ||
22 | |||
23 | typedef struct mutex mutex_t; | ||
24 | |||
25 | #endif /* __XFS_SUPPORT_MUTEX_H__ */ | ||
diff --git a/fs/xfs/linux-2.6/xfs_aops.c b/fs/xfs/linux-2.6/xfs_aops.c index de3a198f771e..c13f67300fe7 100644 --- a/fs/xfs/linux-2.6/xfs_aops.c +++ b/fs/xfs/linux-2.6/xfs_aops.c | |||
@@ -1623,4 +1623,5 @@ const struct address_space_operations xfs_address_space_operations = { | |||
1623 | .bmap = xfs_vm_bmap, | 1623 | .bmap = xfs_vm_bmap, |
1624 | .direct_IO = xfs_vm_direct_IO, | 1624 | .direct_IO = xfs_vm_direct_IO, |
1625 | .migratepage = buffer_migrate_page, | 1625 | .migratepage = buffer_migrate_page, |
1626 | .is_partially_uptodate = block_is_partially_uptodate, | ||
1626 | }; | 1627 | }; |
diff --git a/fs/xfs/linux-2.6/xfs_ioctl.c b/fs/xfs/linux-2.6/xfs_ioctl.c index 4bd112313f33..d0b499418a7d 100644 --- a/fs/xfs/linux-2.6/xfs_ioctl.c +++ b/fs/xfs/linux-2.6/xfs_ioctl.c | |||
@@ -34,6 +34,7 @@ | |||
34 | #include "xfs_dir2_sf.h" | 34 | #include "xfs_dir2_sf.h" |
35 | #include "xfs_dinode.h" | 35 | #include "xfs_dinode.h" |
36 | #include "xfs_inode.h" | 36 | #include "xfs_inode.h" |
37 | #include "xfs_ioctl.h" | ||
37 | #include "xfs_btree.h" | 38 | #include "xfs_btree.h" |
38 | #include "xfs_ialloc.h" | 39 | #include "xfs_ialloc.h" |
39 | #include "xfs_rtalloc.h" | 40 | #include "xfs_rtalloc.h" |
@@ -78,92 +79,74 @@ xfs_find_handle( | |||
78 | int hsize; | 79 | int hsize; |
79 | xfs_handle_t handle; | 80 | xfs_handle_t handle; |
80 | struct inode *inode; | 81 | struct inode *inode; |
82 | struct file *file = NULL; | ||
83 | struct path path; | ||
84 | int error; | ||
85 | struct xfs_inode *ip; | ||
81 | 86 | ||
82 | memset((char *)&handle, 0, sizeof(handle)); | 87 | if (cmd == XFS_IOC_FD_TO_HANDLE) { |
83 | 88 | file = fget(hreq->fd); | |
84 | switch (cmd) { | 89 | if (!file) |
85 | case XFS_IOC_PATH_TO_FSHANDLE: | 90 | return -EBADF; |
86 | case XFS_IOC_PATH_TO_HANDLE: { | 91 | inode = file->f_path.dentry->d_inode; |
87 | struct path path; | 92 | } else { |
88 | int error = user_lpath((const char __user *)hreq->path, &path); | 93 | error = user_lpath((const char __user *)hreq->path, &path); |
89 | if (error) | 94 | if (error) |
90 | return error; | 95 | return error; |
91 | 96 | inode = path.dentry->d_inode; | |
92 | ASSERT(path.dentry); | ||
93 | ASSERT(path.dentry->d_inode); | ||
94 | inode = igrab(path.dentry->d_inode); | ||
95 | path_put(&path); | ||
96 | break; | ||
97 | } | 97 | } |
98 | ip = XFS_I(inode); | ||
98 | 99 | ||
99 | case XFS_IOC_FD_TO_HANDLE: { | 100 | /* |
100 | struct file *file; | 101 | * We can only generate handles for inodes residing on a XFS filesystem, |
101 | 102 | * and only for regular files, directories or symbolic links. | |
102 | file = fget(hreq->fd); | 103 | */ |
103 | if (!file) | 104 | error = -EINVAL; |
104 | return -EBADF; | 105 | if (inode->i_sb->s_magic != XFS_SB_MAGIC) |
106 | goto out_put; | ||
105 | 107 | ||
106 | ASSERT(file->f_path.dentry); | 108 | error = -EBADF; |
107 | ASSERT(file->f_path.dentry->d_inode); | 109 | if (!S_ISREG(inode->i_mode) && |
108 | inode = igrab(file->f_path.dentry->d_inode); | 110 | !S_ISDIR(inode->i_mode) && |
109 | fput(file); | 111 | !S_ISLNK(inode->i_mode)) |
110 | break; | 112 | goto out_put; |
111 | } | ||
112 | 113 | ||
113 | default: | ||
114 | ASSERT(0); | ||
115 | return -XFS_ERROR(EINVAL); | ||
116 | } | ||
117 | 114 | ||
118 | if (inode->i_sb->s_magic != XFS_SB_MAGIC) { | 115 | memcpy(&handle.ha_fsid, ip->i_mount->m_fixedfsid, sizeof(xfs_fsid_t)); |
119 | /* we're not in XFS anymore, Toto */ | ||
120 | iput(inode); | ||
121 | return -XFS_ERROR(EINVAL); | ||
122 | } | ||
123 | 116 | ||
124 | switch (inode->i_mode & S_IFMT) { | 117 | if (cmd == XFS_IOC_PATH_TO_FSHANDLE) { |
125 | case S_IFREG: | 118 | /* |
126 | case S_IFDIR: | 119 | * This handle only contains an fsid, zero the rest. |
127 | case S_IFLNK: | 120 | */ |
128 | break; | 121 | memset(&handle.ha_fid, 0, sizeof(handle.ha_fid)); |
129 | default: | 122 | hsize = sizeof(xfs_fsid_t); |
130 | iput(inode); | 123 | } else { |
131 | return -XFS_ERROR(EBADF); | ||
132 | } | ||
133 | |||
134 | /* now we can grab the fsid */ | ||
135 | memcpy(&handle.ha_fsid, XFS_I(inode)->i_mount->m_fixedfsid, | ||
136 | sizeof(xfs_fsid_t)); | ||
137 | hsize = sizeof(xfs_fsid_t); | ||
138 | |||
139 | if (cmd != XFS_IOC_PATH_TO_FSHANDLE) { | ||
140 | xfs_inode_t *ip = XFS_I(inode); | ||
141 | int lock_mode; | 124 | int lock_mode; |
142 | 125 | ||
143 | /* need to get access to the xfs_inode to read the generation */ | ||
144 | lock_mode = xfs_ilock_map_shared(ip); | 126 | lock_mode = xfs_ilock_map_shared(ip); |
145 | |||
146 | /* fill in fid section of handle from inode */ | ||
147 | handle.ha_fid.fid_len = sizeof(xfs_fid_t) - | 127 | handle.ha_fid.fid_len = sizeof(xfs_fid_t) - |
148 | sizeof(handle.ha_fid.fid_len); | 128 | sizeof(handle.ha_fid.fid_len); |
149 | handle.ha_fid.fid_pad = 0; | 129 | handle.ha_fid.fid_pad = 0; |
150 | handle.ha_fid.fid_gen = ip->i_d.di_gen; | 130 | handle.ha_fid.fid_gen = ip->i_d.di_gen; |
151 | handle.ha_fid.fid_ino = ip->i_ino; | 131 | handle.ha_fid.fid_ino = ip->i_ino; |
152 | |||
153 | xfs_iunlock_map_shared(ip, lock_mode); | 132 | xfs_iunlock_map_shared(ip, lock_mode); |
154 | 133 | ||
155 | hsize = XFS_HSIZE(handle); | 134 | hsize = XFS_HSIZE(handle); |
156 | } | 135 | } |
157 | 136 | ||
158 | /* now copy our handle into the user buffer & write out the size */ | 137 | error = -EFAULT; |
159 | if (copy_to_user(hreq->ohandle, &handle, hsize) || | 138 | if (copy_to_user(hreq->ohandle, &handle, hsize) || |
160 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) { | 139 | copy_to_user(hreq->ohandlen, &hsize, sizeof(__s32))) |
161 | iput(inode); | 140 | goto out_put; |
162 | return -XFS_ERROR(EFAULT); | ||
163 | } | ||
164 | 141 | ||
165 | iput(inode); | 142 | error = 0; |
166 | return 0; | 143 | |
144 | out_put: | ||
145 | if (cmd == XFS_IOC_FD_TO_HANDLE) | ||
146 | fput(file); | ||
147 | else | ||
148 | path_put(&path); | ||
149 | return error; | ||
167 | } | 150 | } |
168 | 151 | ||
169 | /* | 152 | /* |
diff --git a/fs/xfs/linux-2.6/xfs_iops.c b/fs/xfs/linux-2.6/xfs_iops.c index 2940612e3aeb..6075382336d7 100644 --- a/fs/xfs/linux-2.6/xfs_iops.c +++ b/fs/xfs/linux-2.6/xfs_iops.c | |||
@@ -211,8 +211,13 @@ xfs_vn_mknod( | |||
211 | * Irix uses Missed'em'V split, but doesn't want to see | 211 | * Irix uses Missed'em'V split, but doesn't want to see |
212 | * the upper 5 bits of (14bit) major. | 212 | * the upper 5 bits of (14bit) major. |
213 | */ | 213 | */ |
214 | if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) | 214 | if (S_ISCHR(mode) || S_ISBLK(mode)) { |
215 | return -EINVAL; | 215 | if (unlikely(!sysv_valid_dev(rdev) || MAJOR(rdev) & ~0x1ff)) |
216 | return -EINVAL; | ||
217 | rdev = sysv_encode_dev(rdev); | ||
218 | } else { | ||
219 | rdev = 0; | ||
220 | } | ||
216 | 221 | ||
217 | if (test_default_acl && test_default_acl(dir)) { | 222 | if (test_default_acl && test_default_acl(dir)) { |
218 | if (!_ACL_ALLOC(default_acl)) { | 223 | if (!_ACL_ALLOC(default_acl)) { |
@@ -224,28 +229,11 @@ xfs_vn_mknod( | |||
224 | } | 229 | } |
225 | } | 230 | } |
226 | 231 | ||
227 | xfs_dentry_to_name(&name, dentry); | ||
228 | |||
229 | if (IS_POSIXACL(dir) && !default_acl) | 232 | if (IS_POSIXACL(dir) && !default_acl) |
230 | mode &= ~current_umask(); | 233 | mode &= ~current_umask(); |
231 | 234 | ||
232 | switch (mode & S_IFMT) { | 235 | xfs_dentry_to_name(&name, dentry); |
233 | case S_IFCHR: | 236 | error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL); |
234 | case S_IFBLK: | ||
235 | case S_IFIFO: | ||
236 | case S_IFSOCK: | ||
237 | rdev = sysv_encode_dev(rdev); | ||
238 | case S_IFREG: | ||
239 | error = xfs_create(XFS_I(dir), &name, mode, rdev, &ip, NULL); | ||
240 | break; | ||
241 | case S_IFDIR: | ||
242 | error = xfs_mkdir(XFS_I(dir), &name, mode, &ip, NULL); | ||
243 | break; | ||
244 | default: | ||
245 | error = EINVAL; | ||
246 | break; | ||
247 | } | ||
248 | |||
249 | if (unlikely(error)) | 237 | if (unlikely(error)) |
250 | goto out_free_acl; | 238 | goto out_free_acl; |
251 | 239 | ||
@@ -553,9 +541,6 @@ xfs_vn_getattr( | |||
553 | stat->uid = ip->i_d.di_uid; | 541 | stat->uid = ip->i_d.di_uid; |
554 | stat->gid = ip->i_d.di_gid; | 542 | stat->gid = ip->i_d.di_gid; |
555 | stat->ino = ip->i_ino; | 543 | stat->ino = ip->i_ino; |
556 | #if XFS_BIG_INUMS | ||
557 | stat->ino += mp->m_inoadd; | ||
558 | #endif | ||
559 | stat->atime = inode->i_atime; | 544 | stat->atime = inode->i_atime; |
560 | stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec; | 545 | stat->mtime.tv_sec = ip->i_d.di_mtime.t_sec; |
561 | stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; | 546 | stat->mtime.tv_nsec = ip->i_d.di_mtime.t_nsec; |
diff --git a/fs/xfs/linux-2.6/xfs_linux.h b/fs/xfs/linux-2.6/xfs_linux.h index 507492d6dccd..f65a53f8752f 100644 --- a/fs/xfs/linux-2.6/xfs_linux.h +++ b/fs/xfs/linux-2.6/xfs_linux.h | |||
@@ -38,7 +38,6 @@ | |||
38 | #include <kmem.h> | 38 | #include <kmem.h> |
39 | #include <mrlock.h> | 39 | #include <mrlock.h> |
40 | #include <sv.h> | 40 | #include <sv.h> |
41 | #include <mutex.h> | ||
42 | #include <time.h> | 41 | #include <time.h> |
43 | 42 | ||
44 | #include <support/ktrace.h> | 43 | #include <support/ktrace.h> |
@@ -51,6 +50,7 @@ | |||
51 | #include <linux/blkdev.h> | 50 | #include <linux/blkdev.h> |
52 | #include <linux/slab.h> | 51 | #include <linux/slab.h> |
53 | #include <linux/module.h> | 52 | #include <linux/module.h> |
53 | #include <linux/mutex.h> | ||
54 | #include <linux/file.h> | 54 | #include <linux/file.h> |
55 | #include <linux/swap.h> | 55 | #include <linux/swap.h> |
56 | #include <linux/errno.h> | 56 | #include <linux/errno.h> |
@@ -147,17 +147,6 @@ | |||
147 | #define SYNCHRONIZE() barrier() | 147 | #define SYNCHRONIZE() barrier() |
148 | #define __return_address __builtin_return_address(0) | 148 | #define __return_address __builtin_return_address(0) |
149 | 149 | ||
150 | /* | ||
151 | * IRIX (BSD) quotactl makes use of separate commands for user/group, | ||
152 | * whereas on Linux the syscall encodes this information into the cmd | ||
153 | * field (see the QCMD macro in quota.h). These macros help keep the | ||
154 | * code portable - they are not visible from the syscall interface. | ||
155 | */ | ||
156 | #define Q_XSETGQLIM XQM_CMD(8) /* set groups disk limits */ | ||
157 | #define Q_XGETGQUOTA XQM_CMD(9) /* get groups disk limits */ | ||
158 | #define Q_XSETPQLIM XQM_CMD(10) /* set projects disk limits */ | ||
159 | #define Q_XGETPQUOTA XQM_CMD(11) /* get projects disk limits */ | ||
160 | |||
161 | #define dfltprid 0 | 150 | #define dfltprid 0 |
162 | #define MAXPATHLEN 1024 | 151 | #define MAXPATHLEN 1024 |
163 | 152 | ||
diff --git a/fs/xfs/linux-2.6/xfs_quotaops.c b/fs/xfs/linux-2.6/xfs_quotaops.c new file mode 100644 index 000000000000..94d9a633d3d9 --- /dev/null +++ b/fs/xfs/linux-2.6/xfs_quotaops.c | |||
@@ -0,0 +1,157 @@ | |||
1 | /* | ||
2 | * Copyright (c) 2008, Christoph Hellwig | ||
3 | * All Rights Reserved. | ||
4 | * | ||
5 | * This program is free software; you can redistribute it and/or | ||
6 | * modify it under the terms of the GNU General Public License as | ||
7 | * published by the Free Software Foundation. | ||
8 | * | ||
9 | * This program is distributed in the hope that it would be useful, | ||
10 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
11 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
12 | * GNU General Public License for more details. | ||
13 | * | ||
14 | * You should have received a copy of the GNU General Public License | ||
15 | * along with this program; if not, write the Free Software Foundation, | ||
16 | * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA | ||
17 | */ | ||
18 | #include "xfs.h" | ||
19 | #include "xfs_dmapi.h" | ||
20 | #include "xfs_sb.h" | ||
21 | #include "xfs_inum.h" | ||
22 | #include "xfs_ag.h" | ||
23 | #include "xfs_mount.h" | ||
24 | #include "xfs_quota.h" | ||
25 | #include "xfs_log.h" | ||
26 | #include "xfs_trans.h" | ||
27 | #include "xfs_bmap_btree.h" | ||
28 | #include "xfs_inode.h" | ||
29 | #include "quota/xfs_qm.h" | ||
30 | #include <linux/quota.h> | ||
31 | |||
32 | |||
33 | STATIC int | ||
34 | xfs_quota_type(int type) | ||
35 | { | ||
36 | switch (type) { | ||
37 | case USRQUOTA: | ||
38 | return XFS_DQ_USER; | ||
39 | case GRPQUOTA: | ||
40 | return XFS_DQ_GROUP; | ||
41 | default: | ||
42 | return XFS_DQ_PROJ; | ||
43 | } | ||
44 | } | ||
45 | |||
46 | STATIC int | ||
47 | xfs_fs_quota_sync( | ||
48 | struct super_block *sb, | ||
49 | int type) | ||
50 | { | ||
51 | struct xfs_mount *mp = XFS_M(sb); | ||
52 | |||
53 | if (!XFS_IS_QUOTA_RUNNING(mp)) | ||
54 | return -ENOSYS; | ||
55 | return -xfs_sync_inodes(mp, SYNC_DELWRI); | ||
56 | } | ||
57 | |||
58 | STATIC int | ||
59 | xfs_fs_get_xstate( | ||
60 | struct super_block *sb, | ||
61 | struct fs_quota_stat *fqs) | ||
62 | { | ||
63 | struct xfs_mount *mp = XFS_M(sb); | ||
64 | |||
65 | if (!XFS_IS_QUOTA_RUNNING(mp)) | ||
66 | return -ENOSYS; | ||
67 | return -xfs_qm_scall_getqstat(mp, fqs); | ||
68 | } | ||
69 | |||
70 | STATIC int | ||
71 | xfs_fs_set_xstate( | ||
72 | struct super_block *sb, | ||
73 | unsigned int uflags, | ||
74 | int op) | ||
75 | { | ||
76 | struct xfs_mount *mp = XFS_M(sb); | ||
77 | unsigned int flags = 0; | ||
78 | |||
79 | if (sb->s_flags & MS_RDONLY) | ||
80 | return -EROFS; | ||
81 | if (!XFS_IS_QUOTA_RUNNING(mp)) | ||
82 | return -ENOSYS; | ||
83 | if (!capable(CAP_SYS_ADMIN)) | ||
84 | return -EPERM; | ||
85 | |||
86 | if (uflags & XFS_QUOTA_UDQ_ACCT) | ||
87 | flags |= XFS_UQUOTA_ACCT; | ||
88 | if (uflags & XFS_QUOTA_PDQ_ACCT) | ||
89 | flags |= XFS_PQUOTA_ACCT; | ||
90 | if (uflags & XFS_QUOTA_GDQ_ACCT) | ||
91 | flags |= XFS_GQUOTA_ACCT; | ||
92 | if (uflags & XFS_QUOTA_UDQ_ENFD) | ||
93 | flags |= XFS_UQUOTA_ENFD; | ||
94 | if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD)) | ||
95 | flags |= XFS_OQUOTA_ENFD; | ||
96 | |||
97 | switch (op) { | ||
98 | case Q_XQUOTAON: | ||
99 | return -xfs_qm_scall_quotaon(mp, flags); | ||
100 | case Q_XQUOTAOFF: | ||
101 | if (!XFS_IS_QUOTA_ON(mp)) | ||
102 | return -EINVAL; | ||
103 | return -xfs_qm_scall_quotaoff(mp, flags); | ||
104 | case Q_XQUOTARM: | ||
105 | if (XFS_IS_QUOTA_ON(mp)) | ||
106 | return -EINVAL; | ||
107 | return -xfs_qm_scall_trunc_qfiles(mp, flags); | ||
108 | } | ||
109 | |||
110 | return -EINVAL; | ||
111 | } | ||
112 | |||
113 | STATIC int | ||
114 | xfs_fs_get_xquota( | ||
115 | struct super_block *sb, | ||
116 | int type, | ||
117 | qid_t id, | ||
118 | struct fs_disk_quota *fdq) | ||
119 | { | ||
120 | struct xfs_mount *mp = XFS_M(sb); | ||
121 | |||
122 | if (!XFS_IS_QUOTA_RUNNING(mp)) | ||
123 | return -ENOSYS; | ||
124 | if (!XFS_IS_QUOTA_ON(mp)) | ||
125 | return -ESRCH; | ||
126 | |||
127 | return -xfs_qm_scall_getquota(mp, id, xfs_quota_type(type), fdq); | ||
128 | } | ||
129 | |||
130 | STATIC int | ||
131 | xfs_fs_set_xquota( | ||
132 | struct super_block *sb, | ||
133 | int type, | ||
134 | qid_t id, | ||
135 | struct fs_disk_quota *fdq) | ||
136 | { | ||
137 | struct xfs_mount *mp = XFS_M(sb); | ||
138 | |||
139 | if (sb->s_flags & MS_RDONLY) | ||
140 | return -EROFS; | ||
141 | if (!XFS_IS_QUOTA_RUNNING(mp)) | ||
142 | return -ENOSYS; | ||
143 | if (!XFS_IS_QUOTA_ON(mp)) | ||
144 | return -ESRCH; | ||
145 | if (!capable(CAP_SYS_ADMIN)) | ||
146 | return -EPERM; | ||
147 | |||
148 | return -xfs_qm_scall_setqlim(mp, id, xfs_quota_type(type), fdq); | ||
149 | } | ||
150 | |||
151 | struct quotactl_ops xfs_quotactl_operations = { | ||
152 | .quota_sync = xfs_fs_quota_sync, | ||
153 | .get_xstate = xfs_fs_get_xstate, | ||
154 | .set_xstate = xfs_fs_set_xstate, | ||
155 | .get_xquota = xfs_fs_get_xquota, | ||
156 | .set_xquota = xfs_fs_set_xquota, | ||
157 | }; | ||
diff --git a/fs/xfs/linux-2.6/xfs_super.c b/fs/xfs/linux-2.6/xfs_super.c index 32ae5028e96b..bb685269f832 100644 --- a/fs/xfs/linux-2.6/xfs_super.c +++ b/fs/xfs/linux-2.6/xfs_super.c | |||
@@ -68,7 +68,6 @@ | |||
68 | #include <linux/freezer.h> | 68 | #include <linux/freezer.h> |
69 | #include <linux/parser.h> | 69 | #include <linux/parser.h> |
70 | 70 | ||
71 | static struct quotactl_ops xfs_quotactl_operations; | ||
72 | static struct super_operations xfs_super_operations; | 71 | static struct super_operations xfs_super_operations; |
73 | static kmem_zone_t *xfs_ioend_zone; | 72 | static kmem_zone_t *xfs_ioend_zone; |
74 | mempool_t *xfs_ioend_pool; | 73 | mempool_t *xfs_ioend_pool; |
@@ -79,7 +78,6 @@ mempool_t *xfs_ioend_pool; | |||
79 | #define MNTOPT_RTDEV "rtdev" /* realtime I/O device */ | 78 | #define MNTOPT_RTDEV "rtdev" /* realtime I/O device */ |
80 | #define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */ | 79 | #define MNTOPT_BIOSIZE "biosize" /* log2 of preferred buffered io size */ |
81 | #define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */ | 80 | #define MNTOPT_WSYNC "wsync" /* safe-mode nfs compatible mount */ |
82 | #define MNTOPT_INO64 "ino64" /* force inodes into 64-bit range */ | ||
83 | #define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */ | 81 | #define MNTOPT_NOALIGN "noalign" /* turn off stripe alignment */ |
84 | #define MNTOPT_SWALLOC "swalloc" /* turn on stripe width allocation */ | 82 | #define MNTOPT_SWALLOC "swalloc" /* turn on stripe width allocation */ |
85 | #define MNTOPT_SUNIT "sunit" /* data volume stripe unit */ | 83 | #define MNTOPT_SUNIT "sunit" /* data volume stripe unit */ |
@@ -180,7 +178,7 @@ xfs_parseargs( | |||
180 | int dswidth = 0; | 178 | int dswidth = 0; |
181 | int iosize = 0; | 179 | int iosize = 0; |
182 | int dmapi_implies_ikeep = 1; | 180 | int dmapi_implies_ikeep = 1; |
183 | uchar_t iosizelog = 0; | 181 | __uint8_t iosizelog = 0; |
184 | 182 | ||
185 | /* | 183 | /* |
186 | * Copy binary VFS mount flags we are interested in. | 184 | * Copy binary VFS mount flags we are interested in. |
@@ -291,16 +289,6 @@ xfs_parseargs( | |||
291 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; | 289 | mp->m_flags |= XFS_MOUNT_OSYNCISOSYNC; |
292 | } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { | 290 | } else if (!strcmp(this_char, MNTOPT_NORECOVERY)) { |
293 | mp->m_flags |= XFS_MOUNT_NORECOVERY; | 291 | mp->m_flags |= XFS_MOUNT_NORECOVERY; |
294 | } else if (!strcmp(this_char, MNTOPT_INO64)) { | ||
295 | #if XFS_BIG_INUMS | ||
296 | mp->m_flags |= XFS_MOUNT_INO64; | ||
297 | mp->m_inoadd = XFS_INO64_OFFSET; | ||
298 | #else | ||
299 | cmn_err(CE_WARN, | ||
300 | "XFS: %s option not allowed on this system", | ||
301 | this_char); | ||
302 | return EINVAL; | ||
303 | #endif | ||
304 | } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { | 292 | } else if (!strcmp(this_char, MNTOPT_NOALIGN)) { |
305 | mp->m_flags |= XFS_MOUNT_NOALIGN; | 293 | mp->m_flags |= XFS_MOUNT_NOALIGN; |
306 | } else if (!strcmp(this_char, MNTOPT_SWALLOC)) { | 294 | } else if (!strcmp(this_char, MNTOPT_SWALLOC)) { |
@@ -529,7 +517,6 @@ xfs_showargs( | |||
529 | /* the few simple ones we can get from the mount struct */ | 517 | /* the few simple ones we can get from the mount struct */ |
530 | { XFS_MOUNT_IKEEP, "," MNTOPT_IKEEP }, | 518 | { XFS_MOUNT_IKEEP, "," MNTOPT_IKEEP }, |
531 | { XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC }, | 519 | { XFS_MOUNT_WSYNC, "," MNTOPT_WSYNC }, |
532 | { XFS_MOUNT_INO64, "," MNTOPT_INO64 }, | ||
533 | { XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN }, | 520 | { XFS_MOUNT_NOALIGN, "," MNTOPT_NOALIGN }, |
534 | { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC }, | 521 | { XFS_MOUNT_SWALLOC, "," MNTOPT_SWALLOC }, |
535 | { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, | 522 | { XFS_MOUNT_NOUUID, "," MNTOPT_NOUUID }, |
@@ -634,7 +621,7 @@ xfs_max_file_offset( | |||
634 | return (((__uint64_t)pagefactor) << bitshift) - 1; | 621 | return (((__uint64_t)pagefactor) << bitshift) - 1; |
635 | } | 622 | } |
636 | 623 | ||
637 | int | 624 | STATIC int |
638 | xfs_blkdev_get( | 625 | xfs_blkdev_get( |
639 | xfs_mount_t *mp, | 626 | xfs_mount_t *mp, |
640 | const char *name, | 627 | const char *name, |
@@ -651,7 +638,7 @@ xfs_blkdev_get( | |||
651 | return -error; | 638 | return -error; |
652 | } | 639 | } |
653 | 640 | ||
654 | void | 641 | STATIC void |
655 | xfs_blkdev_put( | 642 | xfs_blkdev_put( |
656 | struct block_device *bdev) | 643 | struct block_device *bdev) |
657 | { | 644 | { |
@@ -872,7 +859,7 @@ xfsaild_wakeup( | |||
872 | wake_up_process(ailp->xa_task); | 859 | wake_up_process(ailp->xa_task); |
873 | } | 860 | } |
874 | 861 | ||
875 | int | 862 | STATIC int |
876 | xfsaild( | 863 | xfsaild( |
877 | void *data) | 864 | void *data) |
878 | { | 865 | { |
@@ -990,26 +977,57 @@ xfs_fs_write_inode( | |||
990 | int sync) | 977 | int sync) |
991 | { | 978 | { |
992 | struct xfs_inode *ip = XFS_I(inode); | 979 | struct xfs_inode *ip = XFS_I(inode); |
980 | struct xfs_mount *mp = ip->i_mount; | ||
993 | int error = 0; | 981 | int error = 0; |
994 | int flags = 0; | ||
995 | 982 | ||
996 | xfs_itrace_entry(ip); | 983 | xfs_itrace_entry(ip); |
984 | |||
985 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
986 | return XFS_ERROR(EIO); | ||
987 | |||
997 | if (sync) { | 988 | if (sync) { |
998 | error = xfs_wait_on_pages(ip, 0, -1); | 989 | error = xfs_wait_on_pages(ip, 0, -1); |
999 | if (error) | 990 | if (error) |
1000 | goto out_error; | 991 | goto out; |
1001 | flags |= FLUSH_SYNC; | ||
1002 | } | 992 | } |
1003 | error = xfs_inode_flush(ip, flags); | ||
1004 | 993 | ||
1005 | out_error: | 994 | /* |
995 | * Bypass inodes which have already been cleaned by | ||
996 | * the inode flush clustering code inside xfs_iflush | ||
997 | */ | ||
998 | if (xfs_inode_clean(ip)) | ||
999 | goto out; | ||
1000 | |||
1001 | /* | ||
1002 | * We make this non-blocking if the inode is contended, return | ||
1003 | * EAGAIN to indicate to the caller that they did not succeed. | ||
1004 | * This prevents the flush path from blocking on inodes inside | ||
1005 | * another operation right now, they get caught later by xfs_sync. | ||
1006 | */ | ||
1007 | if (sync) { | ||
1008 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
1009 | xfs_iflock(ip); | ||
1010 | |||
1011 | error = xfs_iflush(ip, XFS_IFLUSH_SYNC); | ||
1012 | } else { | ||
1013 | error = EAGAIN; | ||
1014 | if (!xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) | ||
1015 | goto out; | ||
1016 | if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) | ||
1017 | goto out_unlock; | ||
1018 | |||
1019 | error = xfs_iflush(ip, XFS_IFLUSH_ASYNC_NOBLOCK); | ||
1020 | } | ||
1021 | |||
1022 | out_unlock: | ||
1023 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
1024 | out: | ||
1006 | /* | 1025 | /* |
1007 | * if we failed to write out the inode then mark | 1026 | * if we failed to write out the inode then mark |
1008 | * it dirty again so we'll try again later. | 1027 | * it dirty again so we'll try again later. |
1009 | */ | 1028 | */ |
1010 | if (error) | 1029 | if (error) |
1011 | xfs_mark_inode_dirty_sync(ip); | 1030 | xfs_mark_inode_dirty_sync(ip); |
1012 | |||
1013 | return -error; | 1031 | return -error; |
1014 | } | 1032 | } |
1015 | 1033 | ||
@@ -1169,18 +1187,12 @@ xfs_fs_statfs( | |||
1169 | statp->f_bfree = statp->f_bavail = | 1187 | statp->f_bfree = statp->f_bavail = |
1170 | sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); | 1188 | sbp->sb_fdblocks - XFS_ALLOC_SET_ASIDE(mp); |
1171 | fakeinos = statp->f_bfree << sbp->sb_inopblog; | 1189 | fakeinos = statp->f_bfree << sbp->sb_inopblog; |
1172 | #if XFS_BIG_INUMS | ||
1173 | fakeinos += mp->m_inoadd; | ||
1174 | #endif | ||
1175 | statp->f_files = | 1190 | statp->f_files = |
1176 | MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER); | 1191 | MIN(sbp->sb_icount + fakeinos, (__uint64_t)XFS_MAXINUMBER); |
1177 | if (mp->m_maxicount) | 1192 | if (mp->m_maxicount) |
1178 | #if XFS_BIG_INUMS | 1193 | statp->f_files = min_t(typeof(statp->f_files), |
1179 | if (!mp->m_inoadd) | 1194 | statp->f_files, |
1180 | #endif | 1195 | mp->m_maxicount); |
1181 | statp->f_files = min_t(typeof(statp->f_files), | ||
1182 | statp->f_files, | ||
1183 | mp->m_maxicount); | ||
1184 | statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree); | 1196 | statp->f_ffree = statp->f_files - (sbp->sb_icount - sbp->sb_ifree); |
1185 | spin_unlock(&mp->m_sb_lock); | 1197 | spin_unlock(&mp->m_sb_lock); |
1186 | 1198 | ||
@@ -1302,57 +1314,6 @@ xfs_fs_show_options( | |||
1302 | return -xfs_showargs(XFS_M(mnt->mnt_sb), m); | 1314 | return -xfs_showargs(XFS_M(mnt->mnt_sb), m); |
1303 | } | 1315 | } |
1304 | 1316 | ||
1305 | STATIC int | ||
1306 | xfs_fs_quotasync( | ||
1307 | struct super_block *sb, | ||
1308 | int type) | ||
1309 | { | ||
1310 | return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XQUOTASYNC, 0, NULL); | ||
1311 | } | ||
1312 | |||
1313 | STATIC int | ||
1314 | xfs_fs_getxstate( | ||
1315 | struct super_block *sb, | ||
1316 | struct fs_quota_stat *fqs) | ||
1317 | { | ||
1318 | return -XFS_QM_QUOTACTL(XFS_M(sb), Q_XGETQSTAT, 0, (caddr_t)fqs); | ||
1319 | } | ||
1320 | |||
1321 | STATIC int | ||
1322 | xfs_fs_setxstate( | ||
1323 | struct super_block *sb, | ||
1324 | unsigned int flags, | ||
1325 | int op) | ||
1326 | { | ||
1327 | return -XFS_QM_QUOTACTL(XFS_M(sb), op, 0, (caddr_t)&flags); | ||
1328 | } | ||
1329 | |||
1330 | STATIC int | ||
1331 | xfs_fs_getxquota( | ||
1332 | struct super_block *sb, | ||
1333 | int type, | ||
1334 | qid_t id, | ||
1335 | struct fs_disk_quota *fdq) | ||
1336 | { | ||
1337 | return -XFS_QM_QUOTACTL(XFS_M(sb), | ||
1338 | (type == USRQUOTA) ? Q_XGETQUOTA : | ||
1339 | ((type == GRPQUOTA) ? Q_XGETGQUOTA : | ||
1340 | Q_XGETPQUOTA), id, (caddr_t)fdq); | ||
1341 | } | ||
1342 | |||
1343 | STATIC int | ||
1344 | xfs_fs_setxquota( | ||
1345 | struct super_block *sb, | ||
1346 | int type, | ||
1347 | qid_t id, | ||
1348 | struct fs_disk_quota *fdq) | ||
1349 | { | ||
1350 | return -XFS_QM_QUOTACTL(XFS_M(sb), | ||
1351 | (type == USRQUOTA) ? Q_XSETQLIM : | ||
1352 | ((type == GRPQUOTA) ? Q_XSETGQLIM : | ||
1353 | Q_XSETPQLIM), id, (caddr_t)fdq); | ||
1354 | } | ||
1355 | |||
1356 | /* | 1317 | /* |
1357 | * This function fills in xfs_mount_t fields based on mount args. | 1318 | * This function fills in xfs_mount_t fields based on mount args. |
1358 | * Note: the superblock _has_ now been read in. | 1319 | * Note: the superblock _has_ now been read in. |
@@ -1435,7 +1396,9 @@ xfs_fs_fill_super( | |||
1435 | sb_min_blocksize(sb, BBSIZE); | 1396 | sb_min_blocksize(sb, BBSIZE); |
1436 | sb->s_xattr = xfs_xattr_handlers; | 1397 | sb->s_xattr = xfs_xattr_handlers; |
1437 | sb->s_export_op = &xfs_export_operations; | 1398 | sb->s_export_op = &xfs_export_operations; |
1399 | #ifdef CONFIG_XFS_QUOTA | ||
1438 | sb->s_qcop = &xfs_quotactl_operations; | 1400 | sb->s_qcop = &xfs_quotactl_operations; |
1401 | #endif | ||
1439 | sb->s_op = &xfs_super_operations; | 1402 | sb->s_op = &xfs_super_operations; |
1440 | 1403 | ||
1441 | error = xfs_dmops_get(mp); | 1404 | error = xfs_dmops_get(mp); |
@@ -1578,14 +1541,6 @@ static struct super_operations xfs_super_operations = { | |||
1578 | .show_options = xfs_fs_show_options, | 1541 | .show_options = xfs_fs_show_options, |
1579 | }; | 1542 | }; |
1580 | 1543 | ||
1581 | static struct quotactl_ops xfs_quotactl_operations = { | ||
1582 | .quota_sync = xfs_fs_quotasync, | ||
1583 | .get_xstate = xfs_fs_getxstate, | ||
1584 | .set_xstate = xfs_fs_setxstate, | ||
1585 | .get_xquota = xfs_fs_getxquota, | ||
1586 | .set_xquota = xfs_fs_setxquota, | ||
1587 | }; | ||
1588 | |||
1589 | static struct file_system_type xfs_fs_type = { | 1544 | static struct file_system_type xfs_fs_type = { |
1590 | .owner = THIS_MODULE, | 1545 | .owner = THIS_MODULE, |
1591 | .name = "xfs", | 1546 | .name = "xfs", |
diff --git a/fs/xfs/linux-2.6/xfs_super.h b/fs/xfs/linux-2.6/xfs_super.h index d5d776d4cd67..5a2ea3a21781 100644 --- a/fs/xfs/linux-2.6/xfs_super.h +++ b/fs/xfs/linux-2.6/xfs_super.h | |||
@@ -93,6 +93,7 @@ extern void xfs_blkdev_issue_flush(struct xfs_buftarg *); | |||
93 | 93 | ||
94 | extern const struct export_operations xfs_export_operations; | 94 | extern const struct export_operations xfs_export_operations; |
95 | extern struct xattr_handler *xfs_xattr_handlers[]; | 95 | extern struct xattr_handler *xfs_xattr_handlers[]; |
96 | extern struct quotactl_ops xfs_quotactl_operations; | ||
96 | 97 | ||
97 | #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) | 98 | #define XFS_M(sb) ((struct xfs_mount *)((sb)->s_fs_info)) |
98 | 99 | ||
diff --git a/fs/xfs/linux-2.6/xfs_sync.h b/fs/xfs/linux-2.6/xfs_sync.h index 5f6de1efe1f6..04f058c848ae 100644 --- a/fs/xfs/linux-2.6/xfs_sync.h +++ b/fs/xfs/linux-2.6/xfs_sync.h | |||
@@ -19,6 +19,7 @@ | |||
19 | #define XFS_SYNC_H 1 | 19 | #define XFS_SYNC_H 1 |
20 | 20 | ||
21 | struct xfs_mount; | 21 | struct xfs_mount; |
22 | struct xfs_perag; | ||
22 | 23 | ||
23 | typedef struct bhv_vfs_sync_work { | 24 | typedef struct bhv_vfs_sync_work { |
24 | struct list_head w_list; | 25 | struct list_head w_list; |
diff --git a/fs/xfs/linux-2.6/xfs_vnode.h b/fs/xfs/linux-2.6/xfs_vnode.h index f65983a230d3..ad7fbead4c97 100644 --- a/fs/xfs/linux-2.6/xfs_vnode.h +++ b/fs/xfs/linux-2.6/xfs_vnode.h | |||
@@ -41,11 +41,6 @@ struct attrlist_cursor_kern; | |||
41 | #define IO_INVIS 0x00020 /* don't update inode timestamps */ | 41 | #define IO_INVIS 0x00020 /* don't update inode timestamps */ |
42 | 42 | ||
43 | /* | 43 | /* |
44 | * Flags for xfs_inode_flush | ||
45 | */ | ||
46 | #define FLUSH_SYNC 1 /* wait for flush to complete */ | ||
47 | |||
48 | /* | ||
49 | * Flush/Invalidate options for vop_toss/flush/flushinval_pages. | 44 | * Flush/Invalidate options for vop_toss/flush/flushinval_pages. |
50 | */ | 45 | */ |
51 | #define FI_NONE 0 /* none */ | 46 | #define FI_NONE 0 /* none */ |
@@ -55,33 +50,6 @@ struct attrlist_cursor_kern; | |||
55 | the operation completes. */ | 50 | the operation completes. */ |
56 | 51 | ||
57 | /* | 52 | /* |
58 | * Dealing with bad inodes | ||
59 | */ | ||
60 | static inline int VN_BAD(struct inode *vp) | ||
61 | { | ||
62 | return is_bad_inode(vp); | ||
63 | } | ||
64 | |||
65 | /* | ||
66 | * Extracting atime values in various formats | ||
67 | */ | ||
68 | static inline void vn_atime_to_bstime(struct inode *vp, xfs_bstime_t *bs_atime) | ||
69 | { | ||
70 | bs_atime->tv_sec = vp->i_atime.tv_sec; | ||
71 | bs_atime->tv_nsec = vp->i_atime.tv_nsec; | ||
72 | } | ||
73 | |||
74 | static inline void vn_atime_to_timespec(struct inode *vp, struct timespec *ts) | ||
75 | { | ||
76 | *ts = vp->i_atime; | ||
77 | } | ||
78 | |||
79 | static inline void vn_atime_to_time_t(struct inode *vp, time_t *tt) | ||
80 | { | ||
81 | *tt = vp->i_atime.tv_sec; | ||
82 | } | ||
83 | |||
84 | /* | ||
85 | * Some useful predicates. | 53 | * Some useful predicates. |
86 | */ | 54 | */ |
87 | #define VN_MAPPED(vp) mapping_mapped(vp->i_mapping) | 55 | #define VN_MAPPED(vp) mapping_mapped(vp->i_mapping) |
diff --git a/fs/xfs/quota/xfs_dquot.c b/fs/xfs/quota/xfs_dquot.c index 6543c0b29753..e4babcc63423 100644 --- a/fs/xfs/quota/xfs_dquot.c +++ b/fs/xfs/quota/xfs_dquot.c | |||
@@ -804,7 +804,7 @@ xfs_qm_dqlookup( | |||
804 | uint flist_locked; | 804 | uint flist_locked; |
805 | xfs_dquot_t *d; | 805 | xfs_dquot_t *d; |
806 | 806 | ||
807 | ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); | 807 | ASSERT(mutex_is_locked(&qh->qh_lock)); |
808 | 808 | ||
809 | flist_locked = B_FALSE; | 809 | flist_locked = B_FALSE; |
810 | 810 | ||
@@ -877,7 +877,7 @@ xfs_qm_dqlookup( | |||
877 | /* | 877 | /* |
878 | * move the dquot to the front of the hashchain | 878 | * move the dquot to the front of the hashchain |
879 | */ | 879 | */ |
880 | ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); | 880 | ASSERT(mutex_is_locked(&qh->qh_lock)); |
881 | if (dqp->HL_PREVP != &qh->qh_next) { | 881 | if (dqp->HL_PREVP != &qh->qh_next) { |
882 | xfs_dqtrace_entry(dqp, | 882 | xfs_dqtrace_entry(dqp, |
883 | "DQLOOKUP: HASH MOVETOFRONT"); | 883 | "DQLOOKUP: HASH MOVETOFRONT"); |
@@ -892,13 +892,13 @@ xfs_qm_dqlookup( | |||
892 | } | 892 | } |
893 | xfs_dqtrace_entry(dqp, "LOOKUP END"); | 893 | xfs_dqtrace_entry(dqp, "LOOKUP END"); |
894 | *O_dqpp = dqp; | 894 | *O_dqpp = dqp; |
895 | ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); | 895 | ASSERT(mutex_is_locked(&qh->qh_lock)); |
896 | return (0); | 896 | return (0); |
897 | } | 897 | } |
898 | } | 898 | } |
899 | 899 | ||
900 | *O_dqpp = NULL; | 900 | *O_dqpp = NULL; |
901 | ASSERT(XFS_DQ_IS_HASH_LOCKED(qh)); | 901 | ASSERT(mutex_is_locked(&qh->qh_lock)); |
902 | return (1); | 902 | return (1); |
903 | } | 903 | } |
904 | 904 | ||
@@ -956,7 +956,7 @@ xfs_qm_dqget( | |||
956 | ASSERT(ip->i_gdquot == NULL); | 956 | ASSERT(ip->i_gdquot == NULL); |
957 | } | 957 | } |
958 | #endif | 958 | #endif |
959 | XFS_DQ_HASH_LOCK(h); | 959 | mutex_lock(&h->qh_lock); |
960 | 960 | ||
961 | /* | 961 | /* |
962 | * Look in the cache (hashtable). | 962 | * Look in the cache (hashtable). |
@@ -971,7 +971,7 @@ xfs_qm_dqget( | |||
971 | */ | 971 | */ |
972 | ASSERT(*O_dqpp); | 972 | ASSERT(*O_dqpp); |
973 | ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp)); | 973 | ASSERT(XFS_DQ_IS_LOCKED(*O_dqpp)); |
974 | XFS_DQ_HASH_UNLOCK(h); | 974 | mutex_unlock(&h->qh_lock); |
975 | xfs_dqtrace_entry(*O_dqpp, "DQGET DONE (FROM CACHE)"); | 975 | xfs_dqtrace_entry(*O_dqpp, "DQGET DONE (FROM CACHE)"); |
976 | return (0); /* success */ | 976 | return (0); /* success */ |
977 | } | 977 | } |
@@ -991,7 +991,7 @@ xfs_qm_dqget( | |||
991 | * we don't keep the lock across a disk read | 991 | * we don't keep the lock across a disk read |
992 | */ | 992 | */ |
993 | version = h->qh_version; | 993 | version = h->qh_version; |
994 | XFS_DQ_HASH_UNLOCK(h); | 994 | mutex_unlock(&h->qh_lock); |
995 | 995 | ||
996 | /* | 996 | /* |
997 | * Allocate the dquot on the kernel heap, and read the ondisk | 997 | * Allocate the dquot on the kernel heap, and read the ondisk |
@@ -1056,7 +1056,7 @@ xfs_qm_dqget( | |||
1056 | /* | 1056 | /* |
1057 | * Hashlock comes after ilock in lock order | 1057 | * Hashlock comes after ilock in lock order |
1058 | */ | 1058 | */ |
1059 | XFS_DQ_HASH_LOCK(h); | 1059 | mutex_lock(&h->qh_lock); |
1060 | if (version != h->qh_version) { | 1060 | if (version != h->qh_version) { |
1061 | xfs_dquot_t *tmpdqp; | 1061 | xfs_dquot_t *tmpdqp; |
1062 | /* | 1062 | /* |
@@ -1072,7 +1072,7 @@ xfs_qm_dqget( | |||
1072 | * and start over. | 1072 | * and start over. |
1073 | */ | 1073 | */ |
1074 | xfs_qm_dqput(tmpdqp); | 1074 | xfs_qm_dqput(tmpdqp); |
1075 | XFS_DQ_HASH_UNLOCK(h); | 1075 | mutex_unlock(&h->qh_lock); |
1076 | xfs_qm_dqdestroy(dqp); | 1076 | xfs_qm_dqdestroy(dqp); |
1077 | XQM_STATS_INC(xqmstats.xs_qm_dquot_dups); | 1077 | XQM_STATS_INC(xqmstats.xs_qm_dquot_dups); |
1078 | goto again; | 1078 | goto again; |
@@ -1083,7 +1083,7 @@ xfs_qm_dqget( | |||
1083 | * Put the dquot at the beginning of the hash-chain and mp's list | 1083 | * Put the dquot at the beginning of the hash-chain and mp's list |
1084 | * LOCK ORDER: hashlock, freelistlock, mplistlock, udqlock, gdqlock .. | 1084 | * LOCK ORDER: hashlock, freelistlock, mplistlock, udqlock, gdqlock .. |
1085 | */ | 1085 | */ |
1086 | ASSERT(XFS_DQ_IS_HASH_LOCKED(h)); | 1086 | ASSERT(mutex_is_locked(&h->qh_lock)); |
1087 | dqp->q_hash = h; | 1087 | dqp->q_hash = h; |
1088 | XQM_HASHLIST_INSERT(h, dqp); | 1088 | XQM_HASHLIST_INSERT(h, dqp); |
1089 | 1089 | ||
@@ -1102,7 +1102,7 @@ xfs_qm_dqget( | |||
1102 | XQM_MPLIST_INSERT(&(XFS_QI_MPL_LIST(mp)), dqp); | 1102 | XQM_MPLIST_INSERT(&(XFS_QI_MPL_LIST(mp)), dqp); |
1103 | 1103 | ||
1104 | xfs_qm_mplist_unlock(mp); | 1104 | xfs_qm_mplist_unlock(mp); |
1105 | XFS_DQ_HASH_UNLOCK(h); | 1105 | mutex_unlock(&h->qh_lock); |
1106 | dqret: | 1106 | dqret: |
1107 | ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 1107 | ASSERT((ip == NULL) || xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
1108 | xfs_dqtrace_entry(dqp, "DQGET DONE"); | 1108 | xfs_dqtrace_entry(dqp, "DQGET DONE"); |
@@ -1440,7 +1440,7 @@ xfs_qm_dqpurge( | |||
1440 | xfs_mount_t *mp = dqp->q_mount; | 1440 | xfs_mount_t *mp = dqp->q_mount; |
1441 | 1441 | ||
1442 | ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp)); | 1442 | ASSERT(XFS_QM_IS_MPLIST_LOCKED(mp)); |
1443 | ASSERT(XFS_DQ_IS_HASH_LOCKED(dqp->q_hash)); | 1443 | ASSERT(mutex_is_locked(&dqp->q_hash->qh_lock)); |
1444 | 1444 | ||
1445 | xfs_dqlock(dqp); | 1445 | xfs_dqlock(dqp); |
1446 | /* | 1446 | /* |
@@ -1453,7 +1453,7 @@ xfs_qm_dqpurge( | |||
1453 | */ | 1453 | */ |
1454 | if (dqp->q_nrefs != 0) { | 1454 | if (dqp->q_nrefs != 0) { |
1455 | xfs_dqunlock(dqp); | 1455 | xfs_dqunlock(dqp); |
1456 | XFS_DQ_HASH_UNLOCK(dqp->q_hash); | 1456 | mutex_unlock(&dqp->q_hash->qh_lock); |
1457 | return (1); | 1457 | return (1); |
1458 | } | 1458 | } |
1459 | 1459 | ||
@@ -1517,7 +1517,7 @@ xfs_qm_dqpurge( | |||
1517 | memset(&dqp->q_core, 0, sizeof(dqp->q_core)); | 1517 | memset(&dqp->q_core, 0, sizeof(dqp->q_core)); |
1518 | xfs_dqfunlock(dqp); | 1518 | xfs_dqfunlock(dqp); |
1519 | xfs_dqunlock(dqp); | 1519 | xfs_dqunlock(dqp); |
1520 | XFS_DQ_HASH_UNLOCK(thishash); | 1520 | mutex_unlock(&thishash->qh_lock); |
1521 | return (0); | 1521 | return (0); |
1522 | } | 1522 | } |
1523 | 1523 | ||
diff --git a/fs/xfs/quota/xfs_dquot.h b/fs/xfs/quota/xfs_dquot.h index d443e93b4331..de0f402ddb4c 100644 --- a/fs/xfs/quota/xfs_dquot.h +++ b/fs/xfs/quota/xfs_dquot.h | |||
@@ -34,7 +34,7 @@ | |||
34 | */ | 34 | */ |
35 | typedef struct xfs_dqhash { | 35 | typedef struct xfs_dqhash { |
36 | struct xfs_dquot *qh_next; | 36 | struct xfs_dquot *qh_next; |
37 | mutex_t qh_lock; | 37 | struct mutex qh_lock; |
38 | uint qh_version; /* ever increasing version */ | 38 | uint qh_version; /* ever increasing version */ |
39 | uint qh_nelems; /* number of dquots on the list */ | 39 | uint qh_nelems; /* number of dquots on the list */ |
40 | } xfs_dqhash_t; | 40 | } xfs_dqhash_t; |
@@ -81,7 +81,7 @@ typedef struct xfs_dquot { | |||
81 | xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ | 81 | xfs_qcnt_t q_res_bcount; /* total regular nblks used+reserved */ |
82 | xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ | 82 | xfs_qcnt_t q_res_icount; /* total inos allocd+reserved */ |
83 | xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ | 83 | xfs_qcnt_t q_res_rtbcount;/* total realtime blks used+reserved */ |
84 | mutex_t q_qlock; /* quota lock */ | 84 | struct mutex q_qlock; /* quota lock */ |
85 | struct completion q_flush; /* flush completion queue */ | 85 | struct completion q_flush; /* flush completion queue */ |
86 | atomic_t q_pincount; /* dquot pin count */ | 86 | atomic_t q_pincount; /* dquot pin count */ |
87 | wait_queue_head_t q_pinwait; /* dquot pinning wait queue */ | 87 | wait_queue_head_t q_pinwait; /* dquot pinning wait queue */ |
@@ -109,19 +109,6 @@ enum { | |||
109 | 109 | ||
110 | #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) | 110 | #define XFS_DQHOLD(dqp) ((dqp)->q_nrefs++) |
111 | 111 | ||
112 | #ifdef DEBUG | ||
113 | static inline int | ||
114 | XFS_DQ_IS_LOCKED(xfs_dquot_t *dqp) | ||
115 | { | ||
116 | if (mutex_trylock(&dqp->q_qlock)) { | ||
117 | mutex_unlock(&dqp->q_qlock); | ||
118 | return 0; | ||
119 | } | ||
120 | return 1; | ||
121 | } | ||
122 | #endif | ||
123 | |||
124 | |||
125 | /* | 112 | /* |
126 | * Manage the q_flush completion queue embedded in the dquot. This completion | 113 | * Manage the q_flush completion queue embedded in the dquot. This completion |
127 | * queue synchronizes processes attempting to flush the in-core dquot back to | 114 | * queue synchronizes processes attempting to flush the in-core dquot back to |
@@ -142,6 +129,7 @@ static inline void xfs_dqfunlock(xfs_dquot_t *dqp) | |||
142 | complete(&dqp->q_flush); | 129 | complete(&dqp->q_flush); |
143 | } | 130 | } |
144 | 131 | ||
132 | #define XFS_DQ_IS_LOCKED(dqp) (mutex_is_locked(&((dqp)->q_qlock))) | ||
145 | #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) | 133 | #define XFS_DQ_IS_ON_FREELIST(dqp) ((dqp)->dq_flnext != (dqp)) |
146 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) | 134 | #define XFS_DQ_IS_DIRTY(dqp) ((dqp)->dq_flags & XFS_DQ_DIRTY) |
147 | #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) | 135 | #define XFS_QM_ISUDQ(dqp) ((dqp)->dq_flags & XFS_DQ_USER) |
diff --git a/fs/xfs/quota/xfs_qm.c b/fs/xfs/quota/xfs_qm.c index 7a2beb64314f..5b6695049e00 100644 --- a/fs/xfs/quota/xfs_qm.c +++ b/fs/xfs/quota/xfs_qm.c | |||
@@ -55,7 +55,7 @@ | |||
55 | * quota functionality, including maintaining the freelist and hash | 55 | * quota functionality, including maintaining the freelist and hash |
56 | * tables of dquots. | 56 | * tables of dquots. |
57 | */ | 57 | */ |
58 | mutex_t xfs_Gqm_lock; | 58 | struct mutex xfs_Gqm_lock; |
59 | struct xfs_qm *xfs_Gqm; | 59 | struct xfs_qm *xfs_Gqm; |
60 | uint ndquot; | 60 | uint ndquot; |
61 | 61 | ||
@@ -69,8 +69,6 @@ STATIC void xfs_qm_list_destroy(xfs_dqlist_t *); | |||
69 | 69 | ||
70 | STATIC void xfs_qm_freelist_init(xfs_frlist_t *); | 70 | STATIC void xfs_qm_freelist_init(xfs_frlist_t *); |
71 | STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *); | 71 | STATIC void xfs_qm_freelist_destroy(xfs_frlist_t *); |
72 | STATIC int xfs_qm_mplist_nowait(xfs_mount_t *); | ||
73 | STATIC int xfs_qm_dqhashlock_nowait(xfs_dquot_t *); | ||
74 | 72 | ||
75 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); | 73 | STATIC int xfs_qm_init_quotainos(xfs_mount_t *); |
76 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); | 74 | STATIC int xfs_qm_init_quotainfo(xfs_mount_t *); |
@@ -82,7 +80,7 @@ static struct shrinker xfs_qm_shaker = { | |||
82 | }; | 80 | }; |
83 | 81 | ||
84 | #ifdef DEBUG | 82 | #ifdef DEBUG |
85 | extern mutex_t qcheck_lock; | 83 | extern struct mutex qcheck_lock; |
86 | #endif | 84 | #endif |
87 | 85 | ||
88 | #ifdef QUOTADEBUG | 86 | #ifdef QUOTADEBUG |
@@ -219,7 +217,7 @@ xfs_qm_hold_quotafs_ref( | |||
219 | * the structure could disappear between the entry to this routine and | 217 | * the structure could disappear between the entry to this routine and |
220 | * a HOLD operation if not locked. | 218 | * a HOLD operation if not locked. |
221 | */ | 219 | */ |
222 | XFS_QM_LOCK(xfs_Gqm); | 220 | mutex_lock(&xfs_Gqm_lock); |
223 | 221 | ||
224 | if (xfs_Gqm == NULL) | 222 | if (xfs_Gqm == NULL) |
225 | xfs_Gqm = xfs_Gqm_init(); | 223 | xfs_Gqm = xfs_Gqm_init(); |
@@ -228,8 +226,8 @@ xfs_qm_hold_quotafs_ref( | |||
228 | * debugging and statistical purposes, but ... | 226 | * debugging and statistical purposes, but ... |
229 | * Just take a reference and get out. | 227 | * Just take a reference and get out. |
230 | */ | 228 | */ |
231 | XFS_QM_HOLD(xfs_Gqm); | 229 | xfs_Gqm->qm_nrefs++; |
232 | XFS_QM_UNLOCK(xfs_Gqm); | 230 | mutex_unlock(&xfs_Gqm_lock); |
233 | 231 | ||
234 | return 0; | 232 | return 0; |
235 | } | 233 | } |
@@ -277,13 +275,12 @@ xfs_qm_rele_quotafs_ref( | |||
277 | * Destroy the entire XQM. If somebody mounts with quotaon, this'll | 275 | * Destroy the entire XQM. If somebody mounts with quotaon, this'll |
278 | * be restarted. | 276 | * be restarted. |
279 | */ | 277 | */ |
280 | XFS_QM_LOCK(xfs_Gqm); | 278 | mutex_lock(&xfs_Gqm_lock); |
281 | XFS_QM_RELE(xfs_Gqm); | 279 | if (--xfs_Gqm->qm_nrefs == 0) { |
282 | if (xfs_Gqm->qm_nrefs == 0) { | ||
283 | xfs_qm_destroy(xfs_Gqm); | 280 | xfs_qm_destroy(xfs_Gqm); |
284 | xfs_Gqm = NULL; | 281 | xfs_Gqm = NULL; |
285 | } | 282 | } |
286 | XFS_QM_UNLOCK(xfs_Gqm); | 283 | mutex_unlock(&xfs_Gqm_lock); |
287 | } | 284 | } |
288 | 285 | ||
289 | /* | 286 | /* |
@@ -577,10 +574,10 @@ xfs_qm_dqpurge_int( | |||
577 | continue; | 574 | continue; |
578 | } | 575 | } |
579 | 576 | ||
580 | if (! xfs_qm_dqhashlock_nowait(dqp)) { | 577 | if (!mutex_trylock(&dqp->q_hash->qh_lock)) { |
581 | nrecl = XFS_QI_MPLRECLAIMS(mp); | 578 | nrecl = XFS_QI_MPLRECLAIMS(mp); |
582 | xfs_qm_mplist_unlock(mp); | 579 | xfs_qm_mplist_unlock(mp); |
583 | XFS_DQ_HASH_LOCK(dqp->q_hash); | 580 | mutex_lock(&dqp->q_hash->qh_lock); |
584 | xfs_qm_mplist_lock(mp); | 581 | xfs_qm_mplist_lock(mp); |
585 | 582 | ||
586 | /* | 583 | /* |
@@ -590,7 +587,7 @@ xfs_qm_dqpurge_int( | |||
590 | * this point, but somebody might be taking things off. | 587 | * this point, but somebody might be taking things off. |
591 | */ | 588 | */ |
592 | if (nrecl != XFS_QI_MPLRECLAIMS(mp)) { | 589 | if (nrecl != XFS_QI_MPLRECLAIMS(mp)) { |
593 | XFS_DQ_HASH_UNLOCK(dqp->q_hash); | 590 | mutex_unlock(&dqp->q_hash->qh_lock); |
594 | goto again; | 591 | goto again; |
595 | } | 592 | } |
596 | } | 593 | } |
@@ -632,7 +629,6 @@ xfs_qm_dqattach_one( | |||
632 | xfs_dqid_t id, | 629 | xfs_dqid_t id, |
633 | uint type, | 630 | uint type, |
634 | uint doalloc, | 631 | uint doalloc, |
635 | uint dolock, | ||
636 | xfs_dquot_t *udqhint, /* hint */ | 632 | xfs_dquot_t *udqhint, /* hint */ |
637 | xfs_dquot_t **IO_idqpp) | 633 | xfs_dquot_t **IO_idqpp) |
638 | { | 634 | { |
@@ -641,16 +637,16 @@ xfs_qm_dqattach_one( | |||
641 | 637 | ||
642 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 638 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
643 | error = 0; | 639 | error = 0; |
640 | |||
644 | /* | 641 | /* |
645 | * See if we already have it in the inode itself. IO_idqpp is | 642 | * See if we already have it in the inode itself. IO_idqpp is |
646 | * &i_udquot or &i_gdquot. This made the code look weird, but | 643 | * &i_udquot or &i_gdquot. This made the code look weird, but |
647 | * made the logic a lot simpler. | 644 | * made the logic a lot simpler. |
648 | */ | 645 | */ |
649 | if ((dqp = *IO_idqpp)) { | 646 | dqp = *IO_idqpp; |
650 | if (dolock) | 647 | if (dqp) { |
651 | xfs_dqlock(dqp); | ||
652 | xfs_dqtrace_entry(dqp, "DQATTACH: found in ip"); | 648 | xfs_dqtrace_entry(dqp, "DQATTACH: found in ip"); |
653 | goto done; | 649 | return 0; |
654 | } | 650 | } |
655 | 651 | ||
656 | /* | 652 | /* |
@@ -659,38 +655,38 @@ xfs_qm_dqattach_one( | |||
659 | * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside | 655 | * lookup by dqid (xfs_qm_dqget) by caching a group dquot inside |
660 | * the user dquot. | 656 | * the user dquot. |
661 | */ | 657 | */ |
662 | ASSERT(!udqhint || type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); | 658 | if (udqhint) { |
663 | if (udqhint && !dolock) | 659 | ASSERT(type == XFS_DQ_GROUP || type == XFS_DQ_PROJ); |
664 | xfs_dqlock(udqhint); | 660 | xfs_dqlock(udqhint); |
665 | 661 | ||
666 | /* | 662 | /* |
667 | * No need to take dqlock to look at the id. | 663 | * No need to take dqlock to look at the id. |
668 | * The ID can't change until it gets reclaimed, and it won't | 664 | * |
669 | * be reclaimed as long as we have a ref from inode and we hold | 665 | * The ID can't change until it gets reclaimed, and it won't |
670 | * the ilock. | 666 | * be reclaimed as long as we have a ref from inode and we |
671 | */ | 667 | * hold the ilock. |
672 | if (udqhint && | 668 | */ |
673 | (dqp = udqhint->q_gdquot) && | 669 | dqp = udqhint->q_gdquot; |
674 | (be32_to_cpu(dqp->q_core.d_id) == id)) { | 670 | if (dqp && be32_to_cpu(dqp->q_core.d_id) == id) { |
675 | ASSERT(XFS_DQ_IS_LOCKED(udqhint)); | 671 | xfs_dqlock(dqp); |
676 | xfs_dqlock(dqp); | 672 | XFS_DQHOLD(dqp); |
677 | XFS_DQHOLD(dqp); | 673 | ASSERT(*IO_idqpp == NULL); |
678 | ASSERT(*IO_idqpp == NULL); | 674 | *IO_idqpp = dqp; |
679 | *IO_idqpp = dqp; | 675 | |
680 | if (!dolock) { | ||
681 | xfs_dqunlock(dqp); | 676 | xfs_dqunlock(dqp); |
682 | xfs_dqunlock(udqhint); | 677 | xfs_dqunlock(udqhint); |
678 | return 0; | ||
683 | } | 679 | } |
684 | goto done; | 680 | |
685 | } | 681 | /* |
686 | /* | 682 | * We can't hold a dquot lock when we call the dqget code. |
687 | * We can't hold a dquot lock when we call the dqget code. | 683 | * We'll deadlock in no time, because of (not conforming to) |
688 | * We'll deadlock in no time, because of (not conforming to) | 684 | * lock ordering - the inodelock comes before any dquot lock, |
689 | * lock ordering - the inodelock comes before any dquot lock, | 685 | * and we may drop and reacquire the ilock in xfs_qm_dqget(). |
690 | * and we may drop and reacquire the ilock in xfs_qm_dqget(). | 686 | */ |
691 | */ | ||
692 | if (udqhint) | ||
693 | xfs_dqunlock(udqhint); | 687 | xfs_dqunlock(udqhint); |
688 | } | ||
689 | |||
694 | /* | 690 | /* |
695 | * Find the dquot from somewhere. This bumps the | 691 | * Find the dquot from somewhere. This bumps the |
696 | * reference count of dquot and returns it locked. | 692 | * reference count of dquot and returns it locked. |
@@ -698,48 +694,19 @@ xfs_qm_dqattach_one( | |||
698 | * disk and we didn't ask it to allocate; | 694 | * disk and we didn't ask it to allocate; |
699 | * ESRCH if quotas got turned off suddenly. | 695 | * ESRCH if quotas got turned off suddenly. |
700 | */ | 696 | */ |
701 | if ((error = xfs_qm_dqget(ip->i_mount, ip, id, type, | 697 | error = xfs_qm_dqget(ip->i_mount, ip, id, type, XFS_QMOPT_DOWARN, &dqp); |
702 | doalloc|XFS_QMOPT_DOWARN, &dqp))) { | 698 | if (error) |
703 | if (udqhint && dolock) | 699 | return error; |
704 | xfs_dqlock(udqhint); | ||
705 | goto done; | ||
706 | } | ||
707 | 700 | ||
708 | xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget"); | 701 | xfs_dqtrace_entry(dqp, "DQATTACH: found by dqget"); |
702 | |||
709 | /* | 703 | /* |
710 | * dqget may have dropped and re-acquired the ilock, but it guarantees | 704 | * dqget may have dropped and re-acquired the ilock, but it guarantees |
711 | * that the dquot returned is the one that should go in the inode. | 705 | * that the dquot returned is the one that should go in the inode. |
712 | */ | 706 | */ |
713 | *IO_idqpp = dqp; | 707 | *IO_idqpp = dqp; |
714 | ASSERT(dqp); | 708 | xfs_dqunlock(dqp); |
715 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | 709 | return 0; |
716 | if (! dolock) { | ||
717 | xfs_dqunlock(dqp); | ||
718 | goto done; | ||
719 | } | ||
720 | if (! udqhint) | ||
721 | goto done; | ||
722 | |||
723 | ASSERT(udqhint); | ||
724 | ASSERT(dolock); | ||
725 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
726 | if (! xfs_qm_dqlock_nowait(udqhint)) { | ||
727 | xfs_dqunlock(dqp); | ||
728 | xfs_dqlock(udqhint); | ||
729 | xfs_dqlock(dqp); | ||
730 | } | ||
731 | done: | ||
732 | #ifdef QUOTADEBUG | ||
733 | if (udqhint) { | ||
734 | if (dolock) | ||
735 | ASSERT(XFS_DQ_IS_LOCKED(udqhint)); | ||
736 | } | ||
737 | if (! error) { | ||
738 | if (dolock) | ||
739 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
740 | } | ||
741 | #endif | ||
742 | return error; | ||
743 | } | 710 | } |
744 | 711 | ||
745 | 712 | ||
@@ -754,24 +721,15 @@ xfs_qm_dqattach_one( | |||
754 | STATIC void | 721 | STATIC void |
755 | xfs_qm_dqattach_grouphint( | 722 | xfs_qm_dqattach_grouphint( |
756 | xfs_dquot_t *udq, | 723 | xfs_dquot_t *udq, |
757 | xfs_dquot_t *gdq, | 724 | xfs_dquot_t *gdq) |
758 | uint locked) | ||
759 | { | 725 | { |
760 | xfs_dquot_t *tmp; | 726 | xfs_dquot_t *tmp; |
761 | 727 | ||
762 | #ifdef QUOTADEBUG | 728 | xfs_dqlock(udq); |
763 | if (locked) { | ||
764 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | ||
765 | ASSERT(XFS_DQ_IS_LOCKED(gdq)); | ||
766 | } | ||
767 | #endif | ||
768 | if (! locked) | ||
769 | xfs_dqlock(udq); | ||
770 | 729 | ||
771 | if ((tmp = udq->q_gdquot)) { | 730 | if ((tmp = udq->q_gdquot)) { |
772 | if (tmp == gdq) { | 731 | if (tmp == gdq) { |
773 | if (! locked) | 732 | xfs_dqunlock(udq); |
774 | xfs_dqunlock(udq); | ||
775 | return; | 733 | return; |
776 | } | 734 | } |
777 | 735 | ||
@@ -781,8 +739,6 @@ xfs_qm_dqattach_grouphint( | |||
781 | * because the freelist lock comes before dqlocks. | 739 | * because the freelist lock comes before dqlocks. |
782 | */ | 740 | */ |
783 | xfs_dqunlock(udq); | 741 | xfs_dqunlock(udq); |
784 | if (locked) | ||
785 | xfs_dqunlock(gdq); | ||
786 | /* | 742 | /* |
787 | * we took a hard reference once upon a time in dqget, | 743 | * we took a hard reference once upon a time in dqget, |
788 | * so give it back when the udquot no longer points at it | 744 | * so give it back when the udquot no longer points at it |
@@ -795,9 +751,7 @@ xfs_qm_dqattach_grouphint( | |||
795 | 751 | ||
796 | } else { | 752 | } else { |
797 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | 753 | ASSERT(XFS_DQ_IS_LOCKED(udq)); |
798 | if (! locked) { | 754 | xfs_dqlock(gdq); |
799 | xfs_dqlock(gdq); | ||
800 | } | ||
801 | } | 755 | } |
802 | 756 | ||
803 | ASSERT(XFS_DQ_IS_LOCKED(udq)); | 757 | ASSERT(XFS_DQ_IS_LOCKED(udq)); |
@@ -810,10 +764,9 @@ xfs_qm_dqattach_grouphint( | |||
810 | XFS_DQHOLD(gdq); | 764 | XFS_DQHOLD(gdq); |
811 | udq->q_gdquot = gdq; | 765 | udq->q_gdquot = gdq; |
812 | } | 766 | } |
813 | if (! locked) { | 767 | |
814 | xfs_dqunlock(gdq); | 768 | xfs_dqunlock(gdq); |
815 | xfs_dqunlock(udq); | 769 | xfs_dqunlock(udq); |
816 | } | ||
817 | } | 770 | } |
818 | 771 | ||
819 | 772 | ||
@@ -821,8 +774,6 @@ xfs_qm_dqattach_grouphint( | |||
821 | * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON | 774 | * Given a locked inode, attach dquot(s) to it, taking U/G/P-QUOTAON |
822 | * into account. | 775 | * into account. |
823 | * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. | 776 | * If XFS_QMOPT_DQALLOC, the dquot(s) will be allocated if needed. |
824 | * If XFS_QMOPT_DQLOCK, the dquot(s) will be returned locked. This option pretty | ||
825 | * much made this code a complete mess, but it has been pretty useful. | ||
826 | * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL. | 777 | * If XFS_QMOPT_ILOCKED, then inode sent is already locked EXCL. |
827 | * Inode may get unlocked and relocked in here, and the caller must deal with | 778 | * Inode may get unlocked and relocked in here, and the caller must deal with |
828 | * the consequences. | 779 | * the consequences. |
@@ -851,7 +802,6 @@ xfs_qm_dqattach( | |||
851 | if (XFS_IS_UQUOTA_ON(mp)) { | 802 | if (XFS_IS_UQUOTA_ON(mp)) { |
852 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, | 803 | error = xfs_qm_dqattach_one(ip, ip->i_d.di_uid, XFS_DQ_USER, |
853 | flags & XFS_QMOPT_DQALLOC, | 804 | flags & XFS_QMOPT_DQALLOC, |
854 | flags & XFS_QMOPT_DQLOCK, | ||
855 | NULL, &ip->i_udquot); | 805 | NULL, &ip->i_udquot); |
856 | if (error) | 806 | if (error) |
857 | goto done; | 807 | goto done; |
@@ -863,11 +813,9 @@ xfs_qm_dqattach( | |||
863 | error = XFS_IS_GQUOTA_ON(mp) ? | 813 | error = XFS_IS_GQUOTA_ON(mp) ? |
864 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, | 814 | xfs_qm_dqattach_one(ip, ip->i_d.di_gid, XFS_DQ_GROUP, |
865 | flags & XFS_QMOPT_DQALLOC, | 815 | flags & XFS_QMOPT_DQALLOC, |
866 | flags & XFS_QMOPT_DQLOCK, | ||
867 | ip->i_udquot, &ip->i_gdquot) : | 816 | ip->i_udquot, &ip->i_gdquot) : |
868 | xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ, | 817 | xfs_qm_dqattach_one(ip, ip->i_d.di_projid, XFS_DQ_PROJ, |
869 | flags & XFS_QMOPT_DQALLOC, | 818 | flags & XFS_QMOPT_DQALLOC, |
870 | flags & XFS_QMOPT_DQLOCK, | ||
871 | ip->i_udquot, &ip->i_gdquot); | 819 | ip->i_udquot, &ip->i_gdquot); |
872 | /* | 820 | /* |
873 | * Don't worry about the udquot that we may have | 821 | * Don't worry about the udquot that we may have |
@@ -898,22 +846,13 @@ xfs_qm_dqattach( | |||
898 | /* | 846 | /* |
899 | * Attach i_gdquot to the gdquot hint inside the i_udquot. | 847 | * Attach i_gdquot to the gdquot hint inside the i_udquot. |
900 | */ | 848 | */ |
901 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot, | 849 | xfs_qm_dqattach_grouphint(ip->i_udquot, ip->i_gdquot); |
902 | flags & XFS_QMOPT_DQLOCK); | ||
903 | } | 850 | } |
904 | 851 | ||
905 | done: | 852 | done: |
906 | 853 | ||
907 | #ifdef QUOTADEBUG | 854 | #ifdef QUOTADEBUG |
908 | if (! error) { | 855 | if (! error) { |
909 | if (ip->i_udquot) { | ||
910 | if (flags & XFS_QMOPT_DQLOCK) | ||
911 | ASSERT(XFS_DQ_IS_LOCKED(ip->i_udquot)); | ||
912 | } | ||
913 | if (ip->i_gdquot) { | ||
914 | if (flags & XFS_QMOPT_DQLOCK) | ||
915 | ASSERT(XFS_DQ_IS_LOCKED(ip->i_gdquot)); | ||
916 | } | ||
917 | if (XFS_IS_UQUOTA_ON(mp)) | 856 | if (XFS_IS_UQUOTA_ON(mp)) |
918 | ASSERT(ip->i_udquot); | 857 | ASSERT(ip->i_udquot); |
919 | if (XFS_IS_OQUOTA_ON(mp)) | 858 | if (XFS_IS_OQUOTA_ON(mp)) |
@@ -2086,7 +2025,7 @@ xfs_qm_shake_freelist( | |||
2086 | * a dqlookup process that holds the hashlock that is | 2025 | * a dqlookup process that holds the hashlock that is |
2087 | * waiting for the freelist lock. | 2026 | * waiting for the freelist lock. |
2088 | */ | 2027 | */ |
2089 | if (! xfs_qm_dqhashlock_nowait(dqp)) { | 2028 | if (!mutex_trylock(&dqp->q_hash->qh_lock)) { |
2090 | xfs_dqfunlock(dqp); | 2029 | xfs_dqfunlock(dqp); |
2091 | xfs_dqunlock(dqp); | 2030 | xfs_dqunlock(dqp); |
2092 | dqp = dqp->dq_flnext; | 2031 | dqp = dqp->dq_flnext; |
@@ -2103,7 +2042,7 @@ xfs_qm_shake_freelist( | |||
2103 | /* XXX put a sentinel so that we can come back here */ | 2042 | /* XXX put a sentinel so that we can come back here */ |
2104 | xfs_dqfunlock(dqp); | 2043 | xfs_dqfunlock(dqp); |
2105 | xfs_dqunlock(dqp); | 2044 | xfs_dqunlock(dqp); |
2106 | XFS_DQ_HASH_UNLOCK(hash); | 2045 | mutex_unlock(&hash->qh_lock); |
2107 | xfs_qm_freelist_unlock(xfs_Gqm); | 2046 | xfs_qm_freelist_unlock(xfs_Gqm); |
2108 | if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) | 2047 | if (++restarts >= XFS_QM_RECLAIM_MAX_RESTARTS) |
2109 | return nreclaimed; | 2048 | return nreclaimed; |
@@ -2120,7 +2059,7 @@ xfs_qm_shake_freelist( | |||
2120 | XQM_HASHLIST_REMOVE(hash, dqp); | 2059 | XQM_HASHLIST_REMOVE(hash, dqp); |
2121 | xfs_dqfunlock(dqp); | 2060 | xfs_dqfunlock(dqp); |
2122 | xfs_qm_mplist_unlock(dqp->q_mount); | 2061 | xfs_qm_mplist_unlock(dqp->q_mount); |
2123 | XFS_DQ_HASH_UNLOCK(hash); | 2062 | mutex_unlock(&hash->qh_lock); |
2124 | 2063 | ||
2125 | off_freelist: | 2064 | off_freelist: |
2126 | XQM_FREELIST_REMOVE(dqp); | 2065 | XQM_FREELIST_REMOVE(dqp); |
@@ -2262,7 +2201,7 @@ xfs_qm_dqreclaim_one(void) | |||
2262 | continue; | 2201 | continue; |
2263 | } | 2202 | } |
2264 | 2203 | ||
2265 | if (! xfs_qm_dqhashlock_nowait(dqp)) | 2204 | if (!mutex_trylock(&dqp->q_hash->qh_lock)) |
2266 | goto mplistunlock; | 2205 | goto mplistunlock; |
2267 | 2206 | ||
2268 | ASSERT(dqp->q_nrefs == 0); | 2207 | ASSERT(dqp->q_nrefs == 0); |
@@ -2271,7 +2210,7 @@ xfs_qm_dqreclaim_one(void) | |||
2271 | XQM_HASHLIST_REMOVE(dqp->q_hash, dqp); | 2210 | XQM_HASHLIST_REMOVE(dqp->q_hash, dqp); |
2272 | XQM_FREELIST_REMOVE(dqp); | 2211 | XQM_FREELIST_REMOVE(dqp); |
2273 | dqpout = dqp; | 2212 | dqpout = dqp; |
2274 | XFS_DQ_HASH_UNLOCK(dqp->q_hash); | 2213 | mutex_unlock(&dqp->q_hash->qh_lock); |
2275 | mplistunlock: | 2214 | mplistunlock: |
2276 | xfs_qm_mplist_unlock(dqp->q_mount); | 2215 | xfs_qm_mplist_unlock(dqp->q_mount); |
2277 | xfs_dqfunlock(dqp); | 2216 | xfs_dqfunlock(dqp); |
@@ -2774,34 +2713,3 @@ xfs_qm_freelist_append(xfs_frlist_t *ql, xfs_dquot_t *dq) | |||
2774 | { | 2713 | { |
2775 | xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq); | 2714 | xfs_qm_freelist_insert((xfs_frlist_t *)ql->qh_prev, dq); |
2776 | } | 2715 | } |
2777 | |||
2778 | STATIC int | ||
2779 | xfs_qm_dqhashlock_nowait( | ||
2780 | xfs_dquot_t *dqp) | ||
2781 | { | ||
2782 | int locked; | ||
2783 | |||
2784 | locked = mutex_trylock(&((dqp)->q_hash->qh_lock)); | ||
2785 | return locked; | ||
2786 | } | ||
2787 | |||
2788 | int | ||
2789 | xfs_qm_freelist_lock_nowait( | ||
2790 | xfs_qm_t *xqm) | ||
2791 | { | ||
2792 | int locked; | ||
2793 | |||
2794 | locked = mutex_trylock(&(xqm->qm_dqfreelist.qh_lock)); | ||
2795 | return locked; | ||
2796 | } | ||
2797 | |||
2798 | STATIC int | ||
2799 | xfs_qm_mplist_nowait( | ||
2800 | xfs_mount_t *mp) | ||
2801 | { | ||
2802 | int locked; | ||
2803 | |||
2804 | ASSERT(mp->m_quotainfo); | ||
2805 | locked = mutex_trylock(&(XFS_QI_MPLLOCK(mp))); | ||
2806 | return locked; | ||
2807 | } | ||
diff --git a/fs/xfs/quota/xfs_qm.h b/fs/xfs/quota/xfs_qm.h index ddf09166387c..a371954cae1b 100644 --- a/fs/xfs/quota/xfs_qm.h +++ b/fs/xfs/quota/xfs_qm.h | |||
@@ -27,7 +27,7 @@ struct xfs_qm; | |||
27 | struct xfs_inode; | 27 | struct xfs_inode; |
28 | 28 | ||
29 | extern uint ndquot; | 29 | extern uint ndquot; |
30 | extern mutex_t xfs_Gqm_lock; | 30 | extern struct mutex xfs_Gqm_lock; |
31 | extern struct xfs_qm *xfs_Gqm; | 31 | extern struct xfs_qm *xfs_Gqm; |
32 | extern kmem_zone_t *qm_dqzone; | 32 | extern kmem_zone_t *qm_dqzone; |
33 | extern kmem_zone_t *qm_dqtrxzone; | 33 | extern kmem_zone_t *qm_dqtrxzone; |
@@ -79,7 +79,7 @@ typedef xfs_dqhash_t xfs_dqlist_t; | |||
79 | typedef struct xfs_frlist { | 79 | typedef struct xfs_frlist { |
80 | struct xfs_dquot *qh_next; | 80 | struct xfs_dquot *qh_next; |
81 | struct xfs_dquot *qh_prev; | 81 | struct xfs_dquot *qh_prev; |
82 | mutex_t qh_lock; | 82 | struct mutex qh_lock; |
83 | uint qh_version; | 83 | uint qh_version; |
84 | uint qh_nelems; | 84 | uint qh_nelems; |
85 | } xfs_frlist_t; | 85 | } xfs_frlist_t; |
@@ -115,7 +115,7 @@ typedef struct xfs_quotainfo { | |||
115 | xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */ | 115 | xfs_qwarncnt_t qi_bwarnlimit; /* limit for blks warnings */ |
116 | xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */ | 116 | xfs_qwarncnt_t qi_iwarnlimit; /* limit for inodes warnings */ |
117 | xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */ | 117 | xfs_qwarncnt_t qi_rtbwarnlimit;/* limit for rt blks warnings */ |
118 | mutex_t qi_quotaofflock;/* to serialize quotaoff */ | 118 | struct mutex qi_quotaofflock;/* to serialize quotaoff */ |
119 | xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */ | 119 | xfs_filblks_t qi_dqchunklen; /* # BBs in a chunk of dqs */ |
120 | uint qi_dqperchunk; /* # ondisk dqs in above chunk */ | 120 | uint qi_dqperchunk; /* # ondisk dqs in above chunk */ |
121 | xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */ | 121 | xfs_qcnt_t qi_bhardlimit; /* default data blk hard limit */ |
@@ -158,11 +158,6 @@ typedef struct xfs_dquot_acct { | |||
158 | #define XFS_QM_IWARNLIMIT 5 | 158 | #define XFS_QM_IWARNLIMIT 5 |
159 | #define XFS_QM_RTBWARNLIMIT 5 | 159 | #define XFS_QM_RTBWARNLIMIT 5 |
160 | 160 | ||
161 | #define XFS_QM_LOCK(xqm) (mutex_lock(&xqm##_lock)) | ||
162 | #define XFS_QM_UNLOCK(xqm) (mutex_unlock(&xqm##_lock)) | ||
163 | #define XFS_QM_HOLD(xqm) ((xqm)->qm_nrefs++) | ||
164 | #define XFS_QM_RELE(xqm) ((xqm)->qm_nrefs--) | ||
165 | |||
166 | extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); | 161 | extern void xfs_qm_destroy_quotainfo(xfs_mount_t *); |
167 | extern void xfs_qm_mount_quotas(xfs_mount_t *); | 162 | extern void xfs_qm_mount_quotas(xfs_mount_t *); |
168 | extern int xfs_qm_quotacheck(xfs_mount_t *); | 163 | extern int xfs_qm_quotacheck(xfs_mount_t *); |
@@ -178,6 +173,16 @@ extern void xfs_qm_dqdetach(xfs_inode_t *); | |||
178 | extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); | 173 | extern int xfs_qm_dqpurge_all(xfs_mount_t *, uint); |
179 | extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); | 174 | extern void xfs_qm_dqrele_all_inodes(xfs_mount_t *, uint); |
180 | 175 | ||
176 | /* quota ops */ | ||
177 | extern int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint); | ||
178 | extern int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint, | ||
179 | fs_disk_quota_t *); | ||
180 | extern int xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint, | ||
181 | fs_disk_quota_t *); | ||
182 | extern int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *); | ||
183 | extern int xfs_qm_scall_quotaon(xfs_mount_t *, uint); | ||
184 | extern int xfs_qm_scall_quotaoff(xfs_mount_t *, uint); | ||
185 | |||
181 | /* vop stuff */ | 186 | /* vop stuff */ |
182 | extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, | 187 | extern int xfs_qm_vop_dqalloc(xfs_mount_t *, xfs_inode_t *, |
183 | uid_t, gid_t, prid_t, uint, | 188 | uid_t, gid_t, prid_t, uint, |
@@ -194,11 +199,6 @@ extern int xfs_qm_vop_chown_reserve(xfs_trans_t *, xfs_inode_t *, | |||
194 | /* list stuff */ | 199 | /* list stuff */ |
195 | extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *); | 200 | extern void xfs_qm_freelist_append(xfs_frlist_t *, xfs_dquot_t *); |
196 | extern void xfs_qm_freelist_unlink(xfs_dquot_t *); | 201 | extern void xfs_qm_freelist_unlink(xfs_dquot_t *); |
197 | extern int xfs_qm_freelist_lock_nowait(xfs_qm_t *); | ||
198 | |||
199 | /* system call interface */ | ||
200 | extern int xfs_qm_quotactl(struct xfs_mount *, int, int, | ||
201 | xfs_caddr_t); | ||
202 | 202 | ||
203 | #ifdef DEBUG | 203 | #ifdef DEBUG |
204 | extern int xfs_qm_internalqcheck(xfs_mount_t *); | 204 | extern int xfs_qm_internalqcheck(xfs_mount_t *); |
diff --git a/fs/xfs/quota/xfs_qm_bhv.c b/fs/xfs/quota/xfs_qm_bhv.c index bc6c5cca3e12..63037c689a4b 100644 --- a/fs/xfs/quota/xfs_qm_bhv.c +++ b/fs/xfs/quota/xfs_qm_bhv.c | |||
@@ -235,7 +235,6 @@ struct xfs_qmops xfs_qmcore_xfs = { | |||
235 | .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve, | 235 | .xfs_dqvopchownresv = xfs_qm_vop_chown_reserve, |
236 | .xfs_dqstatvfs = xfs_qm_statvfs, | 236 | .xfs_dqstatvfs = xfs_qm_statvfs, |
237 | .xfs_dqsync = xfs_qm_sync, | 237 | .xfs_dqsync = xfs_qm_sync, |
238 | .xfs_quotactl = xfs_qm_quotactl, | ||
239 | .xfs_dqtrxops = &xfs_trans_dquot_ops, | 238 | .xfs_dqtrxops = &xfs_trans_dquot_ops, |
240 | }; | 239 | }; |
241 | EXPORT_SYMBOL(xfs_qmcore_xfs); | 240 | EXPORT_SYMBOL(xfs_qmcore_xfs); |
diff --git a/fs/xfs/quota/xfs_qm_syscalls.c b/fs/xfs/quota/xfs_qm_syscalls.c index 68139b38aede..c7b66f6506ce 100644 --- a/fs/xfs/quota/xfs_qm_syscalls.c +++ b/fs/xfs/quota/xfs_qm_syscalls.c | |||
@@ -57,135 +57,16 @@ | |||
57 | # define qdprintk(s, args...) do { } while (0) | 57 | # define qdprintk(s, args...) do { } while (0) |
58 | #endif | 58 | #endif |
59 | 59 | ||
60 | STATIC int xfs_qm_scall_trunc_qfiles(xfs_mount_t *, uint); | ||
61 | STATIC int xfs_qm_scall_getquota(xfs_mount_t *, xfs_dqid_t, uint, | ||
62 | fs_disk_quota_t *); | ||
63 | STATIC int xfs_qm_scall_getqstat(xfs_mount_t *, fs_quota_stat_t *); | ||
64 | STATIC int xfs_qm_scall_setqlim(xfs_mount_t *, xfs_dqid_t, uint, | ||
65 | fs_disk_quota_t *); | ||
66 | STATIC int xfs_qm_scall_quotaon(xfs_mount_t *, uint); | ||
67 | STATIC int xfs_qm_scall_quotaoff(xfs_mount_t *, uint, boolean_t); | ||
68 | STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); | 60 | STATIC int xfs_qm_log_quotaoff(xfs_mount_t *, xfs_qoff_logitem_t **, uint); |
69 | STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, | 61 | STATIC int xfs_qm_log_quotaoff_end(xfs_mount_t *, xfs_qoff_logitem_t *, |
70 | uint); | 62 | uint); |
71 | STATIC uint xfs_qm_import_flags(uint); | ||
72 | STATIC uint xfs_qm_export_flags(uint); | 63 | STATIC uint xfs_qm_export_flags(uint); |
73 | STATIC uint xfs_qm_import_qtype_flags(uint); | ||
74 | STATIC uint xfs_qm_export_qtype_flags(uint); | 64 | STATIC uint xfs_qm_export_qtype_flags(uint); |
75 | STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *, | 65 | STATIC void xfs_qm_export_dquot(xfs_mount_t *, xfs_disk_dquot_t *, |
76 | fs_disk_quota_t *); | 66 | fs_disk_quota_t *); |
77 | 67 | ||
78 | 68 | ||
79 | /* | 69 | /* |
80 | * The main distribution switch of all XFS quotactl system calls. | ||
81 | */ | ||
82 | int | ||
83 | xfs_qm_quotactl( | ||
84 | xfs_mount_t *mp, | ||
85 | int cmd, | ||
86 | int id, | ||
87 | xfs_caddr_t addr) | ||
88 | { | ||
89 | int error; | ||
90 | |||
91 | ASSERT(addr != NULL || cmd == Q_XQUOTASYNC); | ||
92 | |||
93 | /* | ||
94 | * The following commands are valid even when quotaoff. | ||
95 | */ | ||
96 | switch (cmd) { | ||
97 | case Q_XQUOTARM: | ||
98 | /* | ||
99 | * Truncate quota files. quota must be off. | ||
100 | */ | ||
101 | if (XFS_IS_QUOTA_ON(mp)) | ||
102 | return XFS_ERROR(EINVAL); | ||
103 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
104 | return XFS_ERROR(EROFS); | ||
105 | return (xfs_qm_scall_trunc_qfiles(mp, | ||
106 | xfs_qm_import_qtype_flags(*(uint *)addr))); | ||
107 | |||
108 | case Q_XGETQSTAT: | ||
109 | /* | ||
110 | * Get quota status information. | ||
111 | */ | ||
112 | return (xfs_qm_scall_getqstat(mp, (fs_quota_stat_t *)addr)); | ||
113 | |||
114 | case Q_XQUOTAON: | ||
115 | /* | ||
116 | * QUOTAON - enabling quota enforcement. | ||
117 | * Quota accounting must be turned on at mount time. | ||
118 | */ | ||
119 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
120 | return XFS_ERROR(EROFS); | ||
121 | return (xfs_qm_scall_quotaon(mp, | ||
122 | xfs_qm_import_flags(*(uint *)addr))); | ||
123 | |||
124 | case Q_XQUOTAOFF: | ||
125 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
126 | return XFS_ERROR(EROFS); | ||
127 | break; | ||
128 | |||
129 | case Q_XQUOTASYNC: | ||
130 | return xfs_sync_inodes(mp, SYNC_DELWRI); | ||
131 | |||
132 | default: | ||
133 | break; | ||
134 | } | ||
135 | |||
136 | if (! XFS_IS_QUOTA_ON(mp)) | ||
137 | return XFS_ERROR(ESRCH); | ||
138 | |||
139 | switch (cmd) { | ||
140 | case Q_XQUOTAOFF: | ||
141 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
142 | return XFS_ERROR(EROFS); | ||
143 | error = xfs_qm_scall_quotaoff(mp, | ||
144 | xfs_qm_import_flags(*(uint *)addr), | ||
145 | B_FALSE); | ||
146 | break; | ||
147 | |||
148 | case Q_XGETQUOTA: | ||
149 | error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_USER, | ||
150 | (fs_disk_quota_t *)addr); | ||
151 | break; | ||
152 | case Q_XGETGQUOTA: | ||
153 | error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, | ||
154 | (fs_disk_quota_t *)addr); | ||
155 | break; | ||
156 | case Q_XGETPQUOTA: | ||
157 | error = xfs_qm_scall_getquota(mp, (xfs_dqid_t)id, XFS_DQ_PROJ, | ||
158 | (fs_disk_quota_t *)addr); | ||
159 | break; | ||
160 | |||
161 | case Q_XSETQLIM: | ||
162 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
163 | return XFS_ERROR(EROFS); | ||
164 | error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_USER, | ||
165 | (fs_disk_quota_t *)addr); | ||
166 | break; | ||
167 | case Q_XSETGQLIM: | ||
168 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
169 | return XFS_ERROR(EROFS); | ||
170 | error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_GROUP, | ||
171 | (fs_disk_quota_t *)addr); | ||
172 | break; | ||
173 | case Q_XSETPQLIM: | ||
174 | if (mp->m_flags & XFS_MOUNT_RDONLY) | ||
175 | return XFS_ERROR(EROFS); | ||
176 | error = xfs_qm_scall_setqlim(mp, (xfs_dqid_t)id, XFS_DQ_PROJ, | ||
177 | (fs_disk_quota_t *)addr); | ||
178 | break; | ||
179 | |||
180 | default: | ||
181 | error = XFS_ERROR(EINVAL); | ||
182 | break; | ||
183 | } | ||
184 | |||
185 | return (error); | ||
186 | } | ||
187 | |||
188 | /* | ||
189 | * Turn off quota accounting and/or enforcement for all udquots and/or | 70 | * Turn off quota accounting and/or enforcement for all udquots and/or |
190 | * gdquots. Called only at unmount time. | 71 | * gdquots. Called only at unmount time. |
191 | * | 72 | * |
@@ -193,11 +74,10 @@ xfs_qm_quotactl( | |||
193 | * incore, and modifies the ondisk dquot directly. Therefore, for example, | 74 | * incore, and modifies the ondisk dquot directly. Therefore, for example, |
194 | * it is an error to call this twice, without purging the cache. | 75 | * it is an error to call this twice, without purging the cache. |
195 | */ | 76 | */ |
196 | STATIC int | 77 | int |
197 | xfs_qm_scall_quotaoff( | 78 | xfs_qm_scall_quotaoff( |
198 | xfs_mount_t *mp, | 79 | xfs_mount_t *mp, |
199 | uint flags, | 80 | uint flags) |
200 | boolean_t force) | ||
201 | { | 81 | { |
202 | uint dqtype; | 82 | uint dqtype; |
203 | int error; | 83 | int error; |
@@ -205,8 +85,6 @@ xfs_qm_scall_quotaoff( | |||
205 | xfs_qoff_logitem_t *qoffstart; | 85 | xfs_qoff_logitem_t *qoffstart; |
206 | int nculprits; | 86 | int nculprits; |
207 | 87 | ||
208 | if (!force && !capable(CAP_SYS_ADMIN)) | ||
209 | return XFS_ERROR(EPERM); | ||
210 | /* | 88 | /* |
211 | * No file system can have quotas enabled on disk but not in core. | 89 | * No file system can have quotas enabled on disk but not in core. |
212 | * Note that quota utilities (like quotaoff) _expect_ | 90 | * Note that quota utilities (like quotaoff) _expect_ |
@@ -375,7 +253,7 @@ out_error: | |||
375 | return (error); | 253 | return (error); |
376 | } | 254 | } |
377 | 255 | ||
378 | STATIC int | 256 | int |
379 | xfs_qm_scall_trunc_qfiles( | 257 | xfs_qm_scall_trunc_qfiles( |
380 | xfs_mount_t *mp, | 258 | xfs_mount_t *mp, |
381 | uint flags) | 259 | uint flags) |
@@ -383,8 +261,6 @@ xfs_qm_scall_trunc_qfiles( | |||
383 | int error = 0, error2 = 0; | 261 | int error = 0, error2 = 0; |
384 | xfs_inode_t *qip; | 262 | xfs_inode_t *qip; |
385 | 263 | ||
386 | if (!capable(CAP_SYS_ADMIN)) | ||
387 | return XFS_ERROR(EPERM); | ||
388 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { | 264 | if (!xfs_sb_version_hasquota(&mp->m_sb) || flags == 0) { |
389 | qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); | 265 | qdprintk("qtrunc flags=%x m_qflags=%x\n", flags, mp->m_qflags); |
390 | return XFS_ERROR(EINVAL); | 266 | return XFS_ERROR(EINVAL); |
@@ -416,7 +292,7 @@ xfs_qm_scall_trunc_qfiles( | |||
416 | * effect immediately. | 292 | * effect immediately. |
417 | * (Switching on quota accounting must be done at mount time.) | 293 | * (Switching on quota accounting must be done at mount time.) |
418 | */ | 294 | */ |
419 | STATIC int | 295 | int |
420 | xfs_qm_scall_quotaon( | 296 | xfs_qm_scall_quotaon( |
421 | xfs_mount_t *mp, | 297 | xfs_mount_t *mp, |
422 | uint flags) | 298 | uint flags) |
@@ -426,9 +302,6 @@ xfs_qm_scall_quotaon( | |||
426 | uint accflags; | 302 | uint accflags; |
427 | __int64_t sbflags; | 303 | __int64_t sbflags; |
428 | 304 | ||
429 | if (!capable(CAP_SYS_ADMIN)) | ||
430 | return XFS_ERROR(EPERM); | ||
431 | |||
432 | flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD); | 305 | flags &= (XFS_ALL_QUOTA_ACCT | XFS_ALL_QUOTA_ENFD); |
433 | /* | 306 | /* |
434 | * Switching on quota accounting must be done at mount time. | 307 | * Switching on quota accounting must be done at mount time. |
@@ -517,7 +390,7 @@ xfs_qm_scall_quotaon( | |||
517 | /* | 390 | /* |
518 | * Return quota status information, such as uquota-off, enforcements, etc. | 391 | * Return quota status information, such as uquota-off, enforcements, etc. |
519 | */ | 392 | */ |
520 | STATIC int | 393 | int |
521 | xfs_qm_scall_getqstat( | 394 | xfs_qm_scall_getqstat( |
522 | xfs_mount_t *mp, | 395 | xfs_mount_t *mp, |
523 | fs_quota_stat_t *out) | 396 | fs_quota_stat_t *out) |
@@ -582,7 +455,7 @@ xfs_qm_scall_getqstat( | |||
582 | /* | 455 | /* |
583 | * Adjust quota limits, and start/stop timers accordingly. | 456 | * Adjust quota limits, and start/stop timers accordingly. |
584 | */ | 457 | */ |
585 | STATIC int | 458 | int |
586 | xfs_qm_scall_setqlim( | 459 | xfs_qm_scall_setqlim( |
587 | xfs_mount_t *mp, | 460 | xfs_mount_t *mp, |
588 | xfs_dqid_t id, | 461 | xfs_dqid_t id, |
@@ -595,9 +468,6 @@ xfs_qm_scall_setqlim( | |||
595 | int error; | 468 | int error; |
596 | xfs_qcnt_t hard, soft; | 469 | xfs_qcnt_t hard, soft; |
597 | 470 | ||
598 | if (!capable(CAP_SYS_ADMIN)) | ||
599 | return XFS_ERROR(EPERM); | ||
600 | |||
601 | if ((newlim->d_fieldmask & | 471 | if ((newlim->d_fieldmask & |
602 | (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0) | 472 | (FS_DQ_LIMIT_MASK|FS_DQ_TIMER_MASK|FS_DQ_WARNS_MASK)) == 0) |
603 | return (0); | 473 | return (0); |
@@ -742,7 +612,7 @@ xfs_qm_scall_setqlim( | |||
742 | return error; | 612 | return error; |
743 | } | 613 | } |
744 | 614 | ||
745 | STATIC int | 615 | int |
746 | xfs_qm_scall_getquota( | 616 | xfs_qm_scall_getquota( |
747 | xfs_mount_t *mp, | 617 | xfs_mount_t *mp, |
748 | xfs_dqid_t id, | 618 | xfs_dqid_t id, |
@@ -935,30 +805,6 @@ xfs_qm_export_dquot( | |||
935 | } | 805 | } |
936 | 806 | ||
937 | STATIC uint | 807 | STATIC uint |
938 | xfs_qm_import_qtype_flags( | ||
939 | uint uflags) | ||
940 | { | ||
941 | uint oflags = 0; | ||
942 | |||
943 | /* | ||
944 | * Can't be more than one, or none. | ||
945 | */ | ||
946 | if (((uflags & (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) == | ||
947 | (XFS_GROUP_QUOTA | XFS_USER_QUOTA)) || | ||
948 | ((uflags & (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) == | ||
949 | (XFS_GROUP_QUOTA | XFS_PROJ_QUOTA)) || | ||
950 | ((uflags & (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) == | ||
951 | (XFS_USER_QUOTA | XFS_PROJ_QUOTA)) || | ||
952 | ((uflags & (XFS_GROUP_QUOTA|XFS_USER_QUOTA|XFS_PROJ_QUOTA)) == 0)) | ||
953 | return (0); | ||
954 | |||
955 | oflags |= (uflags & XFS_USER_QUOTA) ? XFS_DQ_USER : 0; | ||
956 | oflags |= (uflags & XFS_PROJ_QUOTA) ? XFS_DQ_PROJ : 0; | ||
957 | oflags |= (uflags & XFS_GROUP_QUOTA) ? XFS_DQ_GROUP: 0; | ||
958 | return oflags; | ||
959 | } | ||
960 | |||
961 | STATIC uint | ||
962 | xfs_qm_export_qtype_flags( | 808 | xfs_qm_export_qtype_flags( |
963 | uint flags) | 809 | uint flags) |
964 | { | 810 | { |
@@ -979,26 +825,6 @@ xfs_qm_export_qtype_flags( | |||
979 | } | 825 | } |
980 | 826 | ||
981 | STATIC uint | 827 | STATIC uint |
982 | xfs_qm_import_flags( | ||
983 | uint uflags) | ||
984 | { | ||
985 | uint flags = 0; | ||
986 | |||
987 | if (uflags & XFS_QUOTA_UDQ_ACCT) | ||
988 | flags |= XFS_UQUOTA_ACCT; | ||
989 | if (uflags & XFS_QUOTA_PDQ_ACCT) | ||
990 | flags |= XFS_PQUOTA_ACCT; | ||
991 | if (uflags & XFS_QUOTA_GDQ_ACCT) | ||
992 | flags |= XFS_GQUOTA_ACCT; | ||
993 | if (uflags & XFS_QUOTA_UDQ_ENFD) | ||
994 | flags |= XFS_UQUOTA_ENFD; | ||
995 | if (uflags & (XFS_QUOTA_PDQ_ENFD|XFS_QUOTA_GDQ_ENFD)) | ||
996 | flags |= XFS_OQUOTA_ENFD; | ||
997 | return (flags); | ||
998 | } | ||
999 | |||
1000 | |||
1001 | STATIC uint | ||
1002 | xfs_qm_export_flags( | 828 | xfs_qm_export_flags( |
1003 | uint flags) | 829 | uint flags) |
1004 | { | 830 | { |
@@ -1134,7 +960,7 @@ xfs_dqhash_t *qmtest_udqtab; | |||
1134 | xfs_dqhash_t *qmtest_gdqtab; | 960 | xfs_dqhash_t *qmtest_gdqtab; |
1135 | int qmtest_hashmask; | 961 | int qmtest_hashmask; |
1136 | int qmtest_nfails; | 962 | int qmtest_nfails; |
1137 | mutex_t qcheck_lock; | 963 | struct mutex qcheck_lock; |
1138 | 964 | ||
1139 | #define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \ | 965 | #define DQTEST_HASHVAL(mp, id) (((__psunsigned_t)(mp) + \ |
1140 | (__psunsigned_t)(id)) & \ | 966 | (__psunsigned_t)(id)) & \ |
diff --git a/fs/xfs/quota/xfs_quota_priv.h b/fs/xfs/quota/xfs_quota_priv.h index c4fcea600bc2..8286b2842b6b 100644 --- a/fs/xfs/quota/xfs_quota_priv.h +++ b/fs/xfs/quota/xfs_quota_priv.h | |||
@@ -42,34 +42,24 @@ | |||
42 | #define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) | 42 | #define XFS_QI_QOFFLOCK(mp) ((mp)->m_quotainfo->qi_quotaofflock) |
43 | 43 | ||
44 | #define XFS_QI_MPL_LIST(mp) ((mp)->m_quotainfo->qi_dqlist) | 44 | #define XFS_QI_MPL_LIST(mp) ((mp)->m_quotainfo->qi_dqlist) |
45 | #define XFS_QI_MPLLOCK(mp) ((mp)->m_quotainfo->qi_dqlist.qh_lock) | ||
46 | #define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next) | 45 | #define XFS_QI_MPLNEXT(mp) ((mp)->m_quotainfo->qi_dqlist.qh_next) |
47 | #define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems) | 46 | #define XFS_QI_MPLNDQUOTS(mp) ((mp)->m_quotainfo->qi_dqlist.qh_nelems) |
48 | 47 | ||
49 | #define XQMLCK(h) (mutex_lock(&((h)->qh_lock))) | 48 | #define xfs_qm_mplist_lock(mp) \ |
50 | #define XQMUNLCK(h) (mutex_unlock(&((h)->qh_lock))) | 49 | mutex_lock(&(XFS_QI_MPL_LIST(mp).qh_lock)) |
51 | #ifdef DEBUG | 50 | #define xfs_qm_mplist_nowait(mp) \ |
52 | struct xfs_dqhash; | 51 | mutex_trylock(&(XFS_QI_MPL_LIST(mp).qh_lock)) |
53 | static inline int XQMISLCKD(struct xfs_dqhash *h) | 52 | #define xfs_qm_mplist_unlock(mp) \ |
54 | { | 53 | mutex_unlock(&(XFS_QI_MPL_LIST(mp).qh_lock)) |
55 | if (mutex_trylock(&h->qh_lock)) { | 54 | #define XFS_QM_IS_MPLIST_LOCKED(mp) \ |
56 | mutex_unlock(&h->qh_lock); | 55 | mutex_is_locked(&(XFS_QI_MPL_LIST(mp).qh_lock)) |
57 | return 0; | 56 | |
58 | } | 57 | #define xfs_qm_freelist_lock(qm) \ |
59 | return 1; | 58 | mutex_lock(&((qm)->qm_dqfreelist.qh_lock)) |
60 | } | 59 | #define xfs_qm_freelist_lock_nowait(qm) \ |
61 | #endif | 60 | mutex_trylock(&((qm)->qm_dqfreelist.qh_lock)) |
62 | 61 | #define xfs_qm_freelist_unlock(qm) \ | |
63 | #define XFS_DQ_HASH_LOCK(h) XQMLCK(h) | 62 | mutex_unlock(&((qm)->qm_dqfreelist.qh_lock)) |
64 | #define XFS_DQ_HASH_UNLOCK(h) XQMUNLCK(h) | ||
65 | #define XFS_DQ_IS_HASH_LOCKED(h) XQMISLCKD(h) | ||
66 | |||
67 | #define xfs_qm_mplist_lock(mp) XQMLCK(&(XFS_QI_MPL_LIST(mp))) | ||
68 | #define xfs_qm_mplist_unlock(mp) XQMUNLCK(&(XFS_QI_MPL_LIST(mp))) | ||
69 | #define XFS_QM_IS_MPLIST_LOCKED(mp) XQMISLCKD(&(XFS_QI_MPL_LIST(mp))) | ||
70 | |||
71 | #define xfs_qm_freelist_lock(qm) XQMLCK(&((qm)->qm_dqfreelist)) | ||
72 | #define xfs_qm_freelist_unlock(qm) XQMUNLCK(&((qm)->qm_dqfreelist)) | ||
73 | 63 | ||
74 | /* | 64 | /* |
75 | * Hash into a bucket in the dquot hash table, based on <mp, id>. | 65 | * Hash into a bucket in the dquot hash table, based on <mp, id>. |
diff --git a/fs/xfs/quota/xfs_trans_dquot.c b/fs/xfs/quota/xfs_trans_dquot.c index 99611381e740..447173bcf96d 100644 --- a/fs/xfs/quota/xfs_trans_dquot.c +++ b/fs/xfs/quota/xfs_trans_dquot.c | |||
@@ -624,10 +624,9 @@ xfs_trans_dqresv( | |||
624 | xfs_qcnt_t *resbcountp; | 624 | xfs_qcnt_t *resbcountp; |
625 | xfs_quotainfo_t *q = mp->m_quotainfo; | 625 | xfs_quotainfo_t *q = mp->m_quotainfo; |
626 | 626 | ||
627 | if (! (flags & XFS_QMOPT_DQLOCK)) { | 627 | |
628 | xfs_dqlock(dqp); | 628 | xfs_dqlock(dqp); |
629 | } | 629 | |
630 | ASSERT(XFS_DQ_IS_LOCKED(dqp)); | ||
631 | if (flags & XFS_TRANS_DQ_RES_BLKS) { | 630 | if (flags & XFS_TRANS_DQ_RES_BLKS) { |
632 | hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit); | 631 | hardlimit = be64_to_cpu(dqp->q_core.d_blk_hardlimit); |
633 | if (!hardlimit) | 632 | if (!hardlimit) |
@@ -740,10 +739,8 @@ xfs_trans_dqresv( | |||
740 | ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount)); | 739 | ASSERT(dqp->q_res_icount >= be64_to_cpu(dqp->q_core.d_icount)); |
741 | 740 | ||
742 | error_return: | 741 | error_return: |
743 | if (! (flags & XFS_QMOPT_DQLOCK)) { | 742 | xfs_dqunlock(dqp); |
744 | xfs_dqunlock(dqp); | 743 | return error; |
745 | } | ||
746 | return (error); | ||
747 | } | 744 | } |
748 | 745 | ||
749 | 746 | ||
@@ -753,8 +750,7 @@ error_return: | |||
753 | * grp/prj quotas is important, because this follows a both-or-nothing | 750 | * grp/prj quotas is important, because this follows a both-or-nothing |
754 | * approach. | 751 | * approach. |
755 | * | 752 | * |
756 | * flags = XFS_QMOPT_DQLOCK indicate if dquot(s) need to be locked. | 753 | * flags = XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. |
757 | * XFS_QMOPT_FORCE_RES evades limit enforcement. Used by chown. | ||
758 | * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. | 754 | * XFS_QMOPT_ENOSPC returns ENOSPC not EDQUOT. Used by pquota. |
759 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks | 755 | * XFS_TRANS_DQ_RES_BLKS reserves regular disk blocks |
760 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks | 756 | * XFS_TRANS_DQ_RES_RTBLKS reserves realtime disk blocks |
diff --git a/fs/xfs/support/debug.c b/fs/xfs/support/debug.c index ae5482965424..3f3610a7ee05 100644 --- a/fs/xfs/support/debug.c +++ b/fs/xfs/support/debug.c | |||
@@ -24,6 +24,7 @@ | |||
24 | #include "xfs_ag.h" | 24 | #include "xfs_ag.h" |
25 | #include "xfs_dmapi.h" | 25 | #include "xfs_dmapi.h" |
26 | #include "xfs_mount.h" | 26 | #include "xfs_mount.h" |
27 | #include "xfs_error.h" | ||
27 | 28 | ||
28 | static char message[1024]; /* keep it off the stack */ | 29 | static char message[1024]; /* keep it off the stack */ |
29 | static DEFINE_SPINLOCK(xfs_err_lock); | 30 | static DEFINE_SPINLOCK(xfs_err_lock); |
diff --git a/fs/xfs/support/uuid.c b/fs/xfs/support/uuid.c index 5830c040ea7e..b83f76b6d410 100644 --- a/fs/xfs/support/uuid.c +++ b/fs/xfs/support/uuid.c | |||
@@ -17,10 +17,6 @@ | |||
17 | */ | 17 | */ |
18 | #include <xfs.h> | 18 | #include <xfs.h> |
19 | 19 | ||
20 | static DEFINE_MUTEX(uuid_monitor); | ||
21 | static int uuid_table_size; | ||
22 | static uuid_t *uuid_table; | ||
23 | |||
24 | /* IRIX interpretation of an uuid_t */ | 20 | /* IRIX interpretation of an uuid_t */ |
25 | typedef struct { | 21 | typedef struct { |
26 | __be32 uu_timelow; | 22 | __be32 uu_timelow; |
@@ -46,12 +42,6 @@ uuid_getnodeuniq(uuid_t *uuid, int fsid [2]) | |||
46 | fsid[1] = be32_to_cpu(uup->uu_timelow); | 42 | fsid[1] = be32_to_cpu(uup->uu_timelow); |
47 | } | 43 | } |
48 | 44 | ||
49 | void | ||
50 | uuid_create_nil(uuid_t *uuid) | ||
51 | { | ||
52 | memset(uuid, 0, sizeof(*uuid)); | ||
53 | } | ||
54 | |||
55 | int | 45 | int |
56 | uuid_is_nil(uuid_t *uuid) | 46 | uuid_is_nil(uuid_t *uuid) |
57 | { | 47 | { |
@@ -71,64 +61,3 @@ uuid_equal(uuid_t *uuid1, uuid_t *uuid2) | |||
71 | { | 61 | { |
72 | return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1; | 62 | return memcmp(uuid1, uuid2, sizeof(uuid_t)) ? 0 : 1; |
73 | } | 63 | } |
74 | |||
75 | /* | ||
76 | * Given a 128-bit uuid, return a 64-bit value by adding the top and bottom | ||
77 | * 64-bit words. NOTE: This function can not be changed EVER. Although | ||
78 | * brain-dead, some applications depend on this 64-bit value remaining | ||
79 | * persistent. Specifically, DMI vendors store the value as a persistent | ||
80 | * filehandle. | ||
81 | */ | ||
82 | __uint64_t | ||
83 | uuid_hash64(uuid_t *uuid) | ||
84 | { | ||
85 | __uint64_t *sp = (__uint64_t *)uuid; | ||
86 | |||
87 | return sp[0] + sp[1]; | ||
88 | } | ||
89 | |||
90 | int | ||
91 | uuid_table_insert(uuid_t *uuid) | ||
92 | { | ||
93 | int i, hole; | ||
94 | |||
95 | mutex_lock(&uuid_monitor); | ||
96 | for (i = 0, hole = -1; i < uuid_table_size; i++) { | ||
97 | if (uuid_is_nil(&uuid_table[i])) { | ||
98 | hole = i; | ||
99 | continue; | ||
100 | } | ||
101 | if (uuid_equal(uuid, &uuid_table[i])) { | ||
102 | mutex_unlock(&uuid_monitor); | ||
103 | return 0; | ||
104 | } | ||
105 | } | ||
106 | if (hole < 0) { | ||
107 | uuid_table = kmem_realloc(uuid_table, | ||
108 | (uuid_table_size + 1) * sizeof(*uuid_table), | ||
109 | uuid_table_size * sizeof(*uuid_table), | ||
110 | KM_SLEEP); | ||
111 | hole = uuid_table_size++; | ||
112 | } | ||
113 | uuid_table[hole] = *uuid; | ||
114 | mutex_unlock(&uuid_monitor); | ||
115 | return 1; | ||
116 | } | ||
117 | |||
118 | void | ||
119 | uuid_table_remove(uuid_t *uuid) | ||
120 | { | ||
121 | int i; | ||
122 | |||
123 | mutex_lock(&uuid_monitor); | ||
124 | for (i = 0; i < uuid_table_size; i++) { | ||
125 | if (uuid_is_nil(&uuid_table[i])) | ||
126 | continue; | ||
127 | if (!uuid_equal(uuid, &uuid_table[i])) | ||
128 | continue; | ||
129 | uuid_create_nil(&uuid_table[i]); | ||
130 | break; | ||
131 | } | ||
132 | ASSERT(i < uuid_table_size); | ||
133 | mutex_unlock(&uuid_monitor); | ||
134 | } | ||
diff --git a/fs/xfs/support/uuid.h b/fs/xfs/support/uuid.h index cff5b607d445..4732d71262cc 100644 --- a/fs/xfs/support/uuid.h +++ b/fs/xfs/support/uuid.h | |||
@@ -22,12 +22,8 @@ typedef struct { | |||
22 | unsigned char __u_bits[16]; | 22 | unsigned char __u_bits[16]; |
23 | } uuid_t; | 23 | } uuid_t; |
24 | 24 | ||
25 | extern void uuid_create_nil(uuid_t *uuid); | ||
26 | extern int uuid_is_nil(uuid_t *uuid); | 25 | extern int uuid_is_nil(uuid_t *uuid); |
27 | extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); | 26 | extern int uuid_equal(uuid_t *uuid1, uuid_t *uuid2); |
28 | extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]); | 27 | extern void uuid_getnodeuniq(uuid_t *uuid, int fsid [2]); |
29 | extern __uint64_t uuid_hash64(uuid_t *uuid); | ||
30 | extern int uuid_table_insert(uuid_t *uuid); | ||
31 | extern void uuid_table_remove(uuid_t *uuid); | ||
32 | 28 | ||
33 | #endif /* __XFS_SUPPORT_UUID_H__ */ | 29 | #endif /* __XFS_SUPPORT_UUID_H__ */ |
diff --git a/fs/xfs/xfs_ag.h b/fs/xfs/xfs_ag.h index 143d63ecb20a..c8641f713caa 100644 --- a/fs/xfs/xfs_ag.h +++ b/fs/xfs/xfs_ag.h | |||
@@ -223,8 +223,8 @@ typedef struct xfs_perag | |||
223 | be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp)) | 223 | be32_to_cpu((a)->agf_levels[XFS_BTNUM_CNTi]), mp)) |
224 | #define XFS_MIN_FREELIST_PAG(pag,mp) \ | 224 | #define XFS_MIN_FREELIST_PAG(pag,mp) \ |
225 | (XFS_MIN_FREELIST_RAW( \ | 225 | (XFS_MIN_FREELIST_RAW( \ |
226 | (uint_t)(pag)->pagf_levels[XFS_BTNUM_BNOi], \ | 226 | (unsigned int)(pag)->pagf_levels[XFS_BTNUM_BNOi], \ |
227 | (uint_t)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp)) | 227 | (unsigned int)(pag)->pagf_levels[XFS_BTNUM_CNTi], mp)) |
228 | 228 | ||
229 | #define XFS_AGB_TO_FSB(mp,agno,agbno) \ | 229 | #define XFS_AGB_TO_FSB(mp,agno,agbno) \ |
230 | (((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno)) | 230 | (((xfs_fsblock_t)(agno) << (mp)->m_sb.sb_agblklog) | (agbno)) |
diff --git a/fs/xfs/xfs_alloc.c b/fs/xfs/xfs_alloc.c index 028e44e58ea9..2cf944eb796d 100644 --- a/fs/xfs/xfs_alloc.c +++ b/fs/xfs/xfs_alloc.c | |||
@@ -1872,6 +1872,25 @@ xfs_alloc_compute_maxlevels( | |||
1872 | } | 1872 | } |
1873 | 1873 | ||
1874 | /* | 1874 | /* |
1875 | * Find the length of the longest extent in an AG. | ||
1876 | */ | ||
1877 | xfs_extlen_t | ||
1878 | xfs_alloc_longest_free_extent( | ||
1879 | struct xfs_mount *mp, | ||
1880 | struct xfs_perag *pag) | ||
1881 | { | ||
1882 | xfs_extlen_t need, delta = 0; | ||
1883 | |||
1884 | need = XFS_MIN_FREELIST_PAG(pag, mp); | ||
1885 | if (need > pag->pagf_flcount) | ||
1886 | delta = need - pag->pagf_flcount; | ||
1887 | |||
1888 | if (pag->pagf_longest > delta) | ||
1889 | return pag->pagf_longest - delta; | ||
1890 | return pag->pagf_flcount > 0 || pag->pagf_longest > 0; | ||
1891 | } | ||
1892 | |||
1893 | /* | ||
1875 | * Decide whether to use this allocation group for this allocation. | 1894 | * Decide whether to use this allocation group for this allocation. |
1876 | * If so, fix up the btree freelist's size. | 1895 | * If so, fix up the btree freelist's size. |
1877 | */ | 1896 | */ |
@@ -1923,15 +1942,12 @@ xfs_alloc_fix_freelist( | |||
1923 | } | 1942 | } |
1924 | 1943 | ||
1925 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { | 1944 | if (!(flags & XFS_ALLOC_FLAG_FREEING)) { |
1926 | need = XFS_MIN_FREELIST_PAG(pag, mp); | ||
1927 | delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; | ||
1928 | /* | 1945 | /* |
1929 | * If it looks like there isn't a long enough extent, or enough | 1946 | * If it looks like there isn't a long enough extent, or enough |
1930 | * total blocks, reject it. | 1947 | * total blocks, reject it. |
1931 | */ | 1948 | */ |
1932 | longest = (pag->pagf_longest > delta) ? | 1949 | need = XFS_MIN_FREELIST_PAG(pag, mp); |
1933 | (pag->pagf_longest - delta) : | 1950 | longest = xfs_alloc_longest_free_extent(mp, pag); |
1934 | (pag->pagf_flcount > 0 || pag->pagf_longest > 0); | ||
1935 | if ((args->minlen + args->alignment + args->minalignslop - 1) > | 1951 | if ((args->minlen + args->alignment + args->minalignslop - 1) > |
1936 | longest || | 1952 | longest || |
1937 | ((int)(pag->pagf_freeblks + pag->pagf_flcount - | 1953 | ((int)(pag->pagf_freeblks + pag->pagf_flcount - |
diff --git a/fs/xfs/xfs_alloc.h b/fs/xfs/xfs_alloc.h index 588172796f7b..e704caee10df 100644 --- a/fs/xfs/xfs_alloc.h +++ b/fs/xfs/xfs_alloc.h | |||
@@ -100,6 +100,12 @@ typedef struct xfs_alloc_arg { | |||
100 | #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ | 100 | #define XFS_ALLOC_USERDATA 1 /* allocation is for user data*/ |
101 | #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ | 101 | #define XFS_ALLOC_INITIAL_USER_DATA 2 /* special case start of file */ |
102 | 102 | ||
103 | /* | ||
104 | * Find the length of the longest extent in an AG. | ||
105 | */ | ||
106 | xfs_extlen_t | ||
107 | xfs_alloc_longest_free_extent(struct xfs_mount *mp, | ||
108 | struct xfs_perag *pag); | ||
103 | 109 | ||
104 | #ifdef __KERNEL__ | 110 | #ifdef __KERNEL__ |
105 | 111 | ||
diff --git a/fs/xfs/xfs_attr_leaf.c b/fs/xfs/xfs_attr_leaf.c index 6c323f8a4cd1..afdc8911637d 100644 --- a/fs/xfs/xfs_attr_leaf.c +++ b/fs/xfs/xfs_attr_leaf.c | |||
@@ -155,7 +155,8 @@ xfs_attr_shortform_bytesfit(xfs_inode_t *dp, int bytes) | |||
155 | * minimum offset only needs to be the space required for | 155 | * minimum offset only needs to be the space required for |
156 | * the btree root. | 156 | * the btree root. |
157 | */ | 157 | */ |
158 | if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > mp->m_attroffset) | 158 | if (!dp->i_d.di_forkoff && dp->i_df.if_bytes > |
159 | xfs_default_attroffset(dp)) | ||
159 | dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); | 160 | dsize = XFS_BMDR_SPACE_CALC(MINDBTPTRS); |
160 | break; | 161 | break; |
161 | 162 | ||
@@ -298,6 +299,26 @@ xfs_attr_shortform_add(xfs_da_args_t *args, int forkoff) | |||
298 | } | 299 | } |
299 | 300 | ||
300 | /* | 301 | /* |
302 | * After the last attribute is removed revert to original inode format, | ||
303 | * making all literal area available to the data fork once more. | ||
304 | */ | ||
305 | STATIC void | ||
306 | xfs_attr_fork_reset( | ||
307 | struct xfs_inode *ip, | ||
308 | struct xfs_trans *tp) | ||
309 | { | ||
310 | xfs_idestroy_fork(ip, XFS_ATTR_FORK); | ||
311 | ip->i_d.di_forkoff = 0; | ||
312 | ip->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
313 | |||
314 | ASSERT(ip->i_d.di_anextents == 0); | ||
315 | ASSERT(ip->i_afp == NULL); | ||
316 | |||
317 | ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t); | ||
318 | xfs_trans_log_inode(tp, ip, XFS_ILOG_CORE); | ||
319 | } | ||
320 | |||
321 | /* | ||
301 | * Remove an attribute from the shortform attribute list structure. | 322 | * Remove an attribute from the shortform attribute list structure. |
302 | */ | 323 | */ |
303 | int | 324 | int |
@@ -344,22 +365,10 @@ xfs_attr_shortform_remove(xfs_da_args_t *args) | |||
344 | */ | 365 | */ |
345 | totsize -= size; | 366 | totsize -= size; |
346 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && | 367 | if (totsize == sizeof(xfs_attr_sf_hdr_t) && |
347 | !(args->op_flags & XFS_DA_OP_ADDNAME) && | 368 | (mp->m_flags & XFS_MOUNT_ATTR2) && |
348 | (mp->m_flags & XFS_MOUNT_ATTR2) && | 369 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE) && |
349 | (dp->i_d.di_format != XFS_DINODE_FMT_BTREE)) { | 370 | !(args->op_flags & XFS_DA_OP_ADDNAME)) { |
350 | /* | 371 | xfs_attr_fork_reset(dp, args->trans); |
351 | * Last attribute now removed, revert to original | ||
352 | * inode format making all literal area available | ||
353 | * to the data fork once more. | ||
354 | */ | ||
355 | xfs_idestroy_fork(dp, XFS_ATTR_FORK); | ||
356 | dp->i_d.di_forkoff = 0; | ||
357 | dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
358 | ASSERT(dp->i_d.di_anextents == 0); | ||
359 | ASSERT(dp->i_afp == NULL); | ||
360 | dp->i_df.if_ext_max = | ||
361 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
362 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
363 | } else { | 372 | } else { |
364 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); | 373 | xfs_idata_realloc(dp, -size, XFS_ATTR_FORK); |
365 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); | 374 | dp->i_d.di_forkoff = xfs_attr_shortform_bytesfit(dp, totsize); |
@@ -786,20 +795,7 @@ xfs_attr_leaf_to_shortform(xfs_dabuf_t *bp, xfs_da_args_t *args, int forkoff) | |||
786 | if (forkoff == -1) { | 795 | if (forkoff == -1) { |
787 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); | 796 | ASSERT(dp->i_mount->m_flags & XFS_MOUNT_ATTR2); |
788 | ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); | 797 | ASSERT(dp->i_d.di_format != XFS_DINODE_FMT_BTREE); |
789 | 798 | xfs_attr_fork_reset(dp, args->trans); | |
790 | /* | ||
791 | * Last attribute was removed, revert to original | ||
792 | * inode format making all literal area available | ||
793 | * to the data fork once more. | ||
794 | */ | ||
795 | xfs_idestroy_fork(dp, XFS_ATTR_FORK); | ||
796 | dp->i_d.di_forkoff = 0; | ||
797 | dp->i_d.di_aformat = XFS_DINODE_FMT_EXTENTS; | ||
798 | ASSERT(dp->i_d.di_anextents == 0); | ||
799 | ASSERT(dp->i_afp == NULL); | ||
800 | dp->i_df.if_ext_max = | ||
801 | XFS_IFORK_DSIZE(dp) / (uint)sizeof(xfs_bmbt_rec_t); | ||
802 | xfs_trans_log_inode(args->trans, dp, XFS_ILOG_CORE); | ||
803 | goto out; | 799 | goto out; |
804 | } | 800 | } |
805 | 801 | ||
diff --git a/fs/xfs/xfs_bmap.c b/fs/xfs/xfs_bmap.c index c852cd65aaea..3a6ed426327a 100644 --- a/fs/xfs/xfs_bmap.c +++ b/fs/xfs/xfs_bmap.c | |||
@@ -2479,7 +2479,7 @@ xfs_bmap_adjacent( | |||
2479 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); | 2479 | fb_agno = nullfb ? NULLAGNUMBER : XFS_FSB_TO_AGNO(mp, ap->firstblock); |
2480 | /* | 2480 | /* |
2481 | * If allocating at eof, and there's a previous real block, | 2481 | * If allocating at eof, and there's a previous real block, |
2482 | * try to use it's last block as our starting point. | 2482 | * try to use its last block as our starting point. |
2483 | */ | 2483 | */ |
2484 | if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF && | 2484 | if (ap->eof && ap->prevp->br_startoff != NULLFILEOFF && |
2485 | !isnullstartblock(ap->prevp->br_startblock) && | 2485 | !isnullstartblock(ap->prevp->br_startblock) && |
@@ -2712,9 +2712,6 @@ xfs_bmap_btalloc( | |||
2712 | xfs_agnumber_t startag; | 2712 | xfs_agnumber_t startag; |
2713 | xfs_alloc_arg_t args; | 2713 | xfs_alloc_arg_t args; |
2714 | xfs_extlen_t blen; | 2714 | xfs_extlen_t blen; |
2715 | xfs_extlen_t delta; | ||
2716 | xfs_extlen_t longest; | ||
2717 | xfs_extlen_t need; | ||
2718 | xfs_extlen_t nextminlen = 0; | 2715 | xfs_extlen_t nextminlen = 0; |
2719 | xfs_perag_t *pag; | 2716 | xfs_perag_t *pag; |
2720 | int nullfb; /* true if ap->firstblock isn't set */ | 2717 | int nullfb; /* true if ap->firstblock isn't set */ |
@@ -2796,13 +2793,8 @@ xfs_bmap_btalloc( | |||
2796 | * See xfs_alloc_fix_freelist... | 2793 | * See xfs_alloc_fix_freelist... |
2797 | */ | 2794 | */ |
2798 | if (pag->pagf_init) { | 2795 | if (pag->pagf_init) { |
2799 | need = XFS_MIN_FREELIST_PAG(pag, mp); | 2796 | xfs_extlen_t longest; |
2800 | delta = need > pag->pagf_flcount ? | 2797 | longest = xfs_alloc_longest_free_extent(mp, pag); |
2801 | need - pag->pagf_flcount : 0; | ||
2802 | longest = (pag->pagf_longest > delta) ? | ||
2803 | (pag->pagf_longest - delta) : | ||
2804 | (pag->pagf_flcount > 0 || | ||
2805 | pag->pagf_longest > 0); | ||
2806 | if (blen < longest) | 2798 | if (blen < longest) |
2807 | blen = longest; | 2799 | blen = longest; |
2808 | } else | 2800 | } else |
@@ -3577,6 +3569,27 @@ xfs_bmap_extents_to_btree( | |||
3577 | } | 3569 | } |
3578 | 3570 | ||
3579 | /* | 3571 | /* |
3572 | * Calculate the default attribute fork offset for newly created inodes. | ||
3573 | */ | ||
3574 | uint | ||
3575 | xfs_default_attroffset( | ||
3576 | struct xfs_inode *ip) | ||
3577 | { | ||
3578 | struct xfs_mount *mp = ip->i_mount; | ||
3579 | uint offset; | ||
3580 | |||
3581 | if (mp->m_sb.sb_inodesize == 256) { | ||
3582 | offset = XFS_LITINO(mp) - | ||
3583 | XFS_BMDR_SPACE_CALC(MINABTPTRS); | ||
3584 | } else { | ||
3585 | offset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS); | ||
3586 | } | ||
3587 | |||
3588 | ASSERT(offset < XFS_LITINO(mp)); | ||
3589 | return offset; | ||
3590 | } | ||
3591 | |||
3592 | /* | ||
3580 | * Helper routine to reset inode di_forkoff field when switching | 3593 | * Helper routine to reset inode di_forkoff field when switching |
3581 | * attribute fork from local to extent format - we reset it where | 3594 | * attribute fork from local to extent format - we reset it where |
3582 | * possible to make space available for inline data fork extents. | 3595 | * possible to make space available for inline data fork extents. |
@@ -3588,15 +3601,18 @@ xfs_bmap_forkoff_reset( | |||
3588 | int whichfork) | 3601 | int whichfork) |
3589 | { | 3602 | { |
3590 | if (whichfork == XFS_ATTR_FORK && | 3603 | if (whichfork == XFS_ATTR_FORK && |
3591 | (ip->i_d.di_format != XFS_DINODE_FMT_DEV) && | 3604 | ip->i_d.di_format != XFS_DINODE_FMT_DEV && |
3592 | (ip->i_d.di_format != XFS_DINODE_FMT_UUID) && | 3605 | ip->i_d.di_format != XFS_DINODE_FMT_UUID && |
3593 | (ip->i_d.di_format != XFS_DINODE_FMT_BTREE) && | 3606 | ip->i_d.di_format != XFS_DINODE_FMT_BTREE) { |
3594 | ((mp->m_attroffset >> 3) > ip->i_d.di_forkoff)) { | 3607 | uint dfl_forkoff = xfs_default_attroffset(ip) >> 3; |
3595 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; | 3608 | |
3596 | ip->i_df.if_ext_max = XFS_IFORK_DSIZE(ip) / | 3609 | if (dfl_forkoff > ip->i_d.di_forkoff) { |
3597 | (uint)sizeof(xfs_bmbt_rec_t); | 3610 | ip->i_d.di_forkoff = dfl_forkoff; |
3598 | ip->i_afp->if_ext_max = XFS_IFORK_ASIZE(ip) / | 3611 | ip->i_df.if_ext_max = |
3599 | (uint)sizeof(xfs_bmbt_rec_t); | 3612 | XFS_IFORK_DSIZE(ip) / sizeof(xfs_bmbt_rec_t); |
3613 | ip->i_afp->if_ext_max = | ||
3614 | XFS_IFORK_ASIZE(ip) / sizeof(xfs_bmbt_rec_t); | ||
3615 | } | ||
3600 | } | 3616 | } |
3601 | } | 3617 | } |
3602 | 3618 | ||
@@ -4065,7 +4081,7 @@ xfs_bmap_add_attrfork( | |||
4065 | case XFS_DINODE_FMT_BTREE: | 4081 | case XFS_DINODE_FMT_BTREE: |
4066 | ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size); | 4082 | ip->i_d.di_forkoff = xfs_attr_shortform_bytesfit(ip, size); |
4067 | if (!ip->i_d.di_forkoff) | 4083 | if (!ip->i_d.di_forkoff) |
4068 | ip->i_d.di_forkoff = mp->m_attroffset >> 3; | 4084 | ip->i_d.di_forkoff = xfs_default_attroffset(ip) >> 3; |
4069 | else if (mp->m_flags & XFS_MOUNT_ATTR2) | 4085 | else if (mp->m_flags & XFS_MOUNT_ATTR2) |
4070 | version = 2; | 4086 | version = 2; |
4071 | break; | 4087 | break; |
@@ -4212,12 +4228,12 @@ xfs_bmap_compute_maxlevels( | |||
4212 | * (a signed 16-bit number, xfs_aextnum_t). | 4228 | * (a signed 16-bit number, xfs_aextnum_t). |
4213 | * | 4229 | * |
4214 | * Note that we can no longer assume that if we are in ATTR1 that | 4230 | * Note that we can no longer assume that if we are in ATTR1 that |
4215 | * the fork offset of all the inodes will be (m_attroffset >> 3) | 4231 | * the fork offset of all the inodes will be |
4216 | * because we could have mounted with ATTR2 and then mounted back | 4232 | * (xfs_default_attroffset(ip) >> 3) because we could have mounted |
4217 | * with ATTR1, keeping the di_forkoff's fixed but probably at | 4233 | * with ATTR2 and then mounted back with ATTR1, keeping the |
4218 | * various positions. Therefore, for both ATTR1 and ATTR2 | 4234 | * di_forkoff's fixed but probably at various positions. Therefore, |
4219 | * we have to assume the worst case scenario of a minimum size | 4235 | * for both ATTR1 and ATTR2 we have to assume the worst case scenario |
4220 | * available. | 4236 | * of a minimum size available. |
4221 | */ | 4237 | */ |
4222 | if (whichfork == XFS_DATA_FORK) { | 4238 | if (whichfork == XFS_DATA_FORK) { |
4223 | maxleafents = MAXEXTNUM; | 4239 | maxleafents = MAXEXTNUM; |
@@ -4804,7 +4820,7 @@ xfs_bmapi( | |||
4804 | xfs_extlen_t minlen; /* min allocation size */ | 4820 | xfs_extlen_t minlen; /* min allocation size */ |
4805 | xfs_mount_t *mp; /* xfs mount structure */ | 4821 | xfs_mount_t *mp; /* xfs mount structure */ |
4806 | int n; /* current extent index */ | 4822 | int n; /* current extent index */ |
4807 | int nallocs; /* number of extents alloc\'d */ | 4823 | int nallocs; /* number of extents alloc'd */ |
4808 | xfs_extnum_t nextents; /* number of extents in file */ | 4824 | xfs_extnum_t nextents; /* number of extents in file */ |
4809 | xfs_fileoff_t obno; /* old block number (offset) */ | 4825 | xfs_fileoff_t obno; /* old block number (offset) */ |
4810 | xfs_bmbt_irec_t prev; /* previous file extent record */ | 4826 | xfs_bmbt_irec_t prev; /* previous file extent record */ |
@@ -6204,7 +6220,7 @@ xfs_bmap_get_bp( | |||
6204 | return(bp); | 6220 | return(bp); |
6205 | } | 6221 | } |
6206 | 6222 | ||
6207 | void | 6223 | STATIC void |
6208 | xfs_check_block( | 6224 | xfs_check_block( |
6209 | struct xfs_btree_block *block, | 6225 | struct xfs_btree_block *block, |
6210 | xfs_mount_t *mp, | 6226 | xfs_mount_t *mp, |
@@ -6494,7 +6510,7 @@ xfs_bmap_count_tree( | |||
6494 | block = XFS_BUF_TO_BLOCK(bp); | 6510 | block = XFS_BUF_TO_BLOCK(bp); |
6495 | 6511 | ||
6496 | if (--level) { | 6512 | if (--level) { |
6497 | /* Not at node above leafs, count this level of nodes */ | 6513 | /* Not at node above leaves, count this level of nodes */ |
6498 | nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); | 6514 | nextbno = be64_to_cpu(block->bb_u.l.bb_rightsib); |
6499 | while (nextbno != NULLFSBLOCK) { | 6515 | while (nextbno != NULLFSBLOCK) { |
6500 | if ((error = xfs_btree_read_bufl(mp, tp, nextbno, | 6516 | if ((error = xfs_btree_read_bufl(mp, tp, nextbno, |
diff --git a/fs/xfs/xfs_bmap.h b/fs/xfs/xfs_bmap.h index be2979d88d32..1b8ff9256bd0 100644 --- a/fs/xfs/xfs_bmap.h +++ b/fs/xfs/xfs_bmap.h | |||
@@ -125,7 +125,7 @@ typedef struct xfs_bmalloca { | |||
125 | struct xfs_bmbt_irec *gotp; /* extent after, or delayed */ | 125 | struct xfs_bmbt_irec *gotp; /* extent after, or delayed */ |
126 | xfs_extlen_t alen; /* i/o length asked/allocated */ | 126 | xfs_extlen_t alen; /* i/o length asked/allocated */ |
127 | xfs_extlen_t total; /* total blocks needed for xaction */ | 127 | xfs_extlen_t total; /* total blocks needed for xaction */ |
128 | xfs_extlen_t minlen; /* mininum allocation size (blocks) */ | 128 | xfs_extlen_t minlen; /* minimum allocation size (blocks) */ |
129 | xfs_extlen_t minleft; /* amount must be left after alloc */ | 129 | xfs_extlen_t minleft; /* amount must be left after alloc */ |
130 | char eof; /* set if allocating past last extent */ | 130 | char eof; /* set if allocating past last extent */ |
131 | char wasdel; /* replacing a delayed allocation */ | 131 | char wasdel; /* replacing a delayed allocation */ |
@@ -338,6 +338,10 @@ xfs_check_nostate_extents( | |||
338 | xfs_extnum_t idx, | 338 | xfs_extnum_t idx, |
339 | xfs_extnum_t num); | 339 | xfs_extnum_t num); |
340 | 340 | ||
341 | uint | ||
342 | xfs_default_attroffset( | ||
343 | struct xfs_inode *ip); | ||
344 | |||
341 | #ifdef __KERNEL__ | 345 | #ifdef __KERNEL__ |
342 | 346 | ||
343 | /* | 347 | /* |
diff --git a/fs/xfs/xfs_btree.c b/fs/xfs/xfs_btree.c index e73c332eb23f..e9df99574829 100644 --- a/fs/xfs/xfs_btree.c +++ b/fs/xfs/xfs_btree.c | |||
@@ -1883,7 +1883,7 @@ xfs_btree_lshift( | |||
1883 | 1883 | ||
1884 | /* | 1884 | /* |
1885 | * We add one entry to the left side and remove one for the right side. | 1885 | * We add one entry to the left side and remove one for the right side. |
1886 | * Accout for it here, the changes will be updated on disk and logged | 1886 | * Account for it here, the changes will be updated on disk and logged |
1887 | * later. | 1887 | * later. |
1888 | */ | 1888 | */ |
1889 | lrecs++; | 1889 | lrecs++; |
@@ -3535,7 +3535,7 @@ xfs_btree_delrec( | |||
3535 | XFS_BTREE_STATS_INC(cur, join); | 3535 | XFS_BTREE_STATS_INC(cur, join); |
3536 | 3536 | ||
3537 | /* | 3537 | /* |
3538 | * Fix up the the number of records and right block pointer in the | 3538 | * Fix up the number of records and right block pointer in the |
3539 | * surviving block, and log it. | 3539 | * surviving block, and log it. |
3540 | */ | 3540 | */ |
3541 | xfs_btree_set_numrecs(left, lrecs + rrecs); | 3541 | xfs_btree_set_numrecs(left, lrecs + rrecs); |
diff --git a/fs/xfs/xfs_btree.h b/fs/xfs/xfs_btree.h index 789fffdf8b2f..4f852b735b96 100644 --- a/fs/xfs/xfs_btree.h +++ b/fs/xfs/xfs_btree.h | |||
@@ -41,7 +41,7 @@ extern kmem_zone_t *xfs_btree_cur_zone; | |||
41 | /* | 41 | /* |
42 | * Generic btree header. | 42 | * Generic btree header. |
43 | * | 43 | * |
44 | * This is a comination of the actual format used on disk for short and long | 44 | * This is a combination of the actual format used on disk for short and long |
45 | * format btrees. The first three fields are shared by both format, but | 45 | * format btrees. The first three fields are shared by both format, but |
46 | * the pointers are different and should be used with care. | 46 | * the pointers are different and should be used with care. |
47 | * | 47 | * |
diff --git a/fs/xfs/xfs_da_btree.c b/fs/xfs/xfs_da_btree.c index c45f74ff1a5b..9ff6e57a5075 100644 --- a/fs/xfs/xfs_da_btree.c +++ b/fs/xfs/xfs_da_btree.c | |||
@@ -1503,7 +1503,7 @@ xfs_da_path_shift(xfs_da_state_t *state, xfs_da_state_path_t *path, | |||
1503 | * This is implemented with some source-level loop unrolling. | 1503 | * This is implemented with some source-level loop unrolling. |
1504 | */ | 1504 | */ |
1505 | xfs_dahash_t | 1505 | xfs_dahash_t |
1506 | xfs_da_hashname(const uchar_t *name, int namelen) | 1506 | xfs_da_hashname(const __uint8_t *name, int namelen) |
1507 | { | 1507 | { |
1508 | xfs_dahash_t hash; | 1508 | xfs_dahash_t hash; |
1509 | 1509 | ||
diff --git a/fs/xfs/xfs_da_btree.h b/fs/xfs/xfs_da_btree.h index 70b710c1792d..8c536167bf75 100644 --- a/fs/xfs/xfs_da_btree.h +++ b/fs/xfs/xfs_da_btree.h | |||
@@ -91,9 +91,9 @@ enum xfs_dacmp { | |||
91 | * Structure to ease passing around component names. | 91 | * Structure to ease passing around component names. |
92 | */ | 92 | */ |
93 | typedef struct xfs_da_args { | 93 | typedef struct xfs_da_args { |
94 | const uchar_t *name; /* string (maybe not NULL terminated) */ | 94 | const __uint8_t *name; /* string (maybe not NULL terminated) */ |
95 | int namelen; /* length of string (maybe no NULL) */ | 95 | int namelen; /* length of string (maybe no NULL) */ |
96 | uchar_t *value; /* set of bytes (maybe contain NULLs) */ | 96 | __uint8_t *value; /* set of bytes (maybe contain NULLs) */ |
97 | int valuelen; /* length of value */ | 97 | int valuelen; /* length of value */ |
98 | int flags; /* argument flags (eg: ATTR_NOCREATE) */ | 98 | int flags; /* argument flags (eg: ATTR_NOCREATE) */ |
99 | xfs_dahash_t hashval; /* hash value of name */ | 99 | xfs_dahash_t hashval; /* hash value of name */ |
@@ -185,7 +185,7 @@ typedef struct xfs_da_state { | |||
185 | unsigned char inleaf; /* insert into 1->lf, 0->splf */ | 185 | unsigned char inleaf; /* insert into 1->lf, 0->splf */ |
186 | unsigned char extravalid; /* T/F: extrablk is in use */ | 186 | unsigned char extravalid; /* T/F: extrablk is in use */ |
187 | unsigned char extraafter; /* T/F: extrablk is after new */ | 187 | unsigned char extraafter; /* T/F: extrablk is after new */ |
188 | xfs_da_state_blk_t extrablk; /* for double-splits on leafs */ | 188 | xfs_da_state_blk_t extrablk; /* for double-splits on leaves */ |
189 | /* for dirv2 extrablk is data */ | 189 | /* for dirv2 extrablk is data */ |
190 | } xfs_da_state_t; | 190 | } xfs_da_state_t; |
191 | 191 | ||
@@ -251,7 +251,7 @@ xfs_daddr_t xfs_da_reada_buf(struct xfs_trans *trans, struct xfs_inode *dp, | |||
251 | int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, | 251 | int xfs_da_shrink_inode(xfs_da_args_t *args, xfs_dablk_t dead_blkno, |
252 | xfs_dabuf_t *dead_buf); | 252 | xfs_dabuf_t *dead_buf); |
253 | 253 | ||
254 | uint xfs_da_hashname(const uchar_t *name_string, int name_length); | 254 | uint xfs_da_hashname(const __uint8_t *name_string, int name_length); |
255 | enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, | 255 | enum xfs_dacmp xfs_da_compname(struct xfs_da_args *args, |
256 | const char *name, int len); | 256 | const char *name, int len); |
257 | 257 | ||
@@ -268,5 +268,6 @@ xfs_daddr_t xfs_da_blkno(xfs_dabuf_t *dabuf); | |||
268 | 268 | ||
269 | extern struct kmem_zone *xfs_da_state_zone; | 269 | extern struct kmem_zone *xfs_da_state_zone; |
270 | extern struct kmem_zone *xfs_dabuf_zone; | 270 | extern struct kmem_zone *xfs_dabuf_zone; |
271 | extern const struct xfs_nameops xfs_default_nameops; | ||
271 | 272 | ||
272 | #endif /* __XFS_DA_BTREE_H__ */ | 273 | #endif /* __XFS_DA_BTREE_H__ */ |
diff --git a/fs/xfs/xfs_dfrag.c b/fs/xfs/xfs_dfrag.c index f8278cfcc1d3..e6d839bddbf0 100644 --- a/fs/xfs/xfs_dfrag.c +++ b/fs/xfs/xfs_dfrag.c | |||
@@ -79,6 +79,12 @@ xfs_swapext( | |||
79 | goto out_put_target_file; | 79 | goto out_put_target_file; |
80 | } | 80 | } |
81 | 81 | ||
82 | if (IS_SWAPFILE(file->f_path.dentry->d_inode) || | ||
83 | IS_SWAPFILE(target_file->f_path.dentry->d_inode)) { | ||
84 | error = XFS_ERROR(EINVAL); | ||
85 | goto out_put_target_file; | ||
86 | } | ||
87 | |||
82 | ip = XFS_I(file->f_path.dentry->d_inode); | 88 | ip = XFS_I(file->f_path.dentry->d_inode); |
83 | tip = XFS_I(target_file->f_path.dentry->d_inode); | 89 | tip = XFS_I(target_file->f_path.dentry->d_inode); |
84 | 90 | ||
@@ -118,19 +124,17 @@ xfs_swap_extents( | |||
118 | xfs_bstat_t *sbp = &sxp->sx_stat; | 124 | xfs_bstat_t *sbp = &sxp->sx_stat; |
119 | xfs_ifork_t *tempifp, *ifp, *tifp; | 125 | xfs_ifork_t *tempifp, *ifp, *tifp; |
120 | int ilf_fields, tilf_fields; | 126 | int ilf_fields, tilf_fields; |
121 | static uint lock_flags = XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL; | ||
122 | int error = 0; | 127 | int error = 0; |
123 | int aforkblks = 0; | 128 | int aforkblks = 0; |
124 | int taforkblks = 0; | 129 | int taforkblks = 0; |
125 | __uint64_t tmp; | 130 | __uint64_t tmp; |
126 | char locked = 0; | ||
127 | 131 | ||
128 | mp = ip->i_mount; | 132 | mp = ip->i_mount; |
129 | 133 | ||
130 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); | 134 | tempifp = kmem_alloc(sizeof(xfs_ifork_t), KM_MAYFAIL); |
131 | if (!tempifp) { | 135 | if (!tempifp) { |
132 | error = XFS_ERROR(ENOMEM); | 136 | error = XFS_ERROR(ENOMEM); |
133 | goto error0; | 137 | goto out; |
134 | } | 138 | } |
135 | 139 | ||
136 | sbp = &sxp->sx_stat; | 140 | sbp = &sxp->sx_stat; |
@@ -143,25 +147,24 @@ xfs_swap_extents( | |||
143 | */ | 147 | */ |
144 | xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); | 148 | xfs_lock_two_inodes(ip, tip, XFS_IOLOCK_EXCL); |
145 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); | 149 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); |
146 | locked = 1; | ||
147 | 150 | ||
148 | /* Verify that both files have the same format */ | 151 | /* Verify that both files have the same format */ |
149 | if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { | 152 | if ((ip->i_d.di_mode & S_IFMT) != (tip->i_d.di_mode & S_IFMT)) { |
150 | error = XFS_ERROR(EINVAL); | 153 | error = XFS_ERROR(EINVAL); |
151 | goto error0; | 154 | goto out_unlock; |
152 | } | 155 | } |
153 | 156 | ||
154 | /* Verify both files are either real-time or non-realtime */ | 157 | /* Verify both files are either real-time or non-realtime */ |
155 | if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) { | 158 | if (XFS_IS_REALTIME_INODE(ip) != XFS_IS_REALTIME_INODE(tip)) { |
156 | error = XFS_ERROR(EINVAL); | 159 | error = XFS_ERROR(EINVAL); |
157 | goto error0; | 160 | goto out_unlock; |
158 | } | 161 | } |
159 | 162 | ||
160 | /* Should never get a local format */ | 163 | /* Should never get a local format */ |
161 | if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL || | 164 | if (ip->i_d.di_format == XFS_DINODE_FMT_LOCAL || |
162 | tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) { | 165 | tip->i_d.di_format == XFS_DINODE_FMT_LOCAL) { |
163 | error = XFS_ERROR(EINVAL); | 166 | error = XFS_ERROR(EINVAL); |
164 | goto error0; | 167 | goto out_unlock; |
165 | } | 168 | } |
166 | 169 | ||
167 | if (VN_CACHED(VFS_I(tip)) != 0) { | 170 | if (VN_CACHED(VFS_I(tip)) != 0) { |
@@ -169,13 +172,13 @@ xfs_swap_extents( | |||
169 | error = xfs_flushinval_pages(tip, 0, -1, | 172 | error = xfs_flushinval_pages(tip, 0, -1, |
170 | FI_REMAPF_LOCKED); | 173 | FI_REMAPF_LOCKED); |
171 | if (error) | 174 | if (error) |
172 | goto error0; | 175 | goto out_unlock; |
173 | } | 176 | } |
174 | 177 | ||
175 | /* Verify O_DIRECT for ftmp */ | 178 | /* Verify O_DIRECT for ftmp */ |
176 | if (VN_CACHED(VFS_I(tip)) != 0) { | 179 | if (VN_CACHED(VFS_I(tip)) != 0) { |
177 | error = XFS_ERROR(EINVAL); | 180 | error = XFS_ERROR(EINVAL); |
178 | goto error0; | 181 | goto out_unlock; |
179 | } | 182 | } |
180 | 183 | ||
181 | /* Verify all data are being swapped */ | 184 | /* Verify all data are being swapped */ |
@@ -183,7 +186,7 @@ xfs_swap_extents( | |||
183 | sxp->sx_length != ip->i_d.di_size || | 186 | sxp->sx_length != ip->i_d.di_size || |
184 | sxp->sx_length != tip->i_d.di_size) { | 187 | sxp->sx_length != tip->i_d.di_size) { |
185 | error = XFS_ERROR(EFAULT); | 188 | error = XFS_ERROR(EFAULT); |
186 | goto error0; | 189 | goto out_unlock; |
187 | } | 190 | } |
188 | 191 | ||
189 | /* | 192 | /* |
@@ -193,7 +196,7 @@ xfs_swap_extents( | |||
193 | */ | 196 | */ |
194 | if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) { | 197 | if ( XFS_IFORK_Q(ip) != XFS_IFORK_Q(tip) ) { |
195 | error = XFS_ERROR(EINVAL); | 198 | error = XFS_ERROR(EINVAL); |
196 | goto error0; | 199 | goto out_unlock; |
197 | } | 200 | } |
198 | 201 | ||
199 | /* | 202 | /* |
@@ -208,7 +211,7 @@ xfs_swap_extents( | |||
208 | (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || | 211 | (sbp->bs_mtime.tv_sec != ip->i_d.di_mtime.t_sec) || |
209 | (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { | 212 | (sbp->bs_mtime.tv_nsec != ip->i_d.di_mtime.t_nsec)) { |
210 | error = XFS_ERROR(EBUSY); | 213 | error = XFS_ERROR(EBUSY); |
211 | goto error0; | 214 | goto out_unlock; |
212 | } | 215 | } |
213 | 216 | ||
214 | /* We need to fail if the file is memory mapped. Once we have tossed | 217 | /* We need to fail if the file is memory mapped. Once we have tossed |
@@ -219,7 +222,7 @@ xfs_swap_extents( | |||
219 | */ | 222 | */ |
220 | if (VN_MAPPED(VFS_I(ip))) { | 223 | if (VN_MAPPED(VFS_I(ip))) { |
221 | error = XFS_ERROR(EBUSY); | 224 | error = XFS_ERROR(EBUSY); |
222 | goto error0; | 225 | goto out_unlock; |
223 | } | 226 | } |
224 | 227 | ||
225 | xfs_iunlock(ip, XFS_ILOCK_EXCL); | 228 | xfs_iunlock(ip, XFS_ILOCK_EXCL); |
@@ -242,8 +245,7 @@ xfs_swap_extents( | |||
242 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); | 245 | xfs_iunlock(ip, XFS_IOLOCK_EXCL); |
243 | xfs_iunlock(tip, XFS_IOLOCK_EXCL); | 246 | xfs_iunlock(tip, XFS_IOLOCK_EXCL); |
244 | xfs_trans_cancel(tp, 0); | 247 | xfs_trans_cancel(tp, 0); |
245 | locked = 0; | 248 | goto out; |
246 | goto error0; | ||
247 | } | 249 | } |
248 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); | 250 | xfs_lock_two_inodes(ip, tip, XFS_ILOCK_EXCL); |
249 | 251 | ||
@@ -253,19 +255,15 @@ xfs_swap_extents( | |||
253 | if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) && | 255 | if ( ((XFS_IFORK_Q(ip) != 0) && (ip->i_d.di_anextents > 0)) && |
254 | (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { | 256 | (ip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { |
255 | error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks); | 257 | error = xfs_bmap_count_blocks(tp, ip, XFS_ATTR_FORK, &aforkblks); |
256 | if (error) { | 258 | if (error) |
257 | xfs_trans_cancel(tp, 0); | 259 | goto out_trans_cancel; |
258 | goto error0; | ||
259 | } | ||
260 | } | 260 | } |
261 | if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && | 261 | if ( ((XFS_IFORK_Q(tip) != 0) && (tip->i_d.di_anextents > 0)) && |
262 | (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { | 262 | (tip->i_d.di_aformat != XFS_DINODE_FMT_LOCAL)) { |
263 | error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, | 263 | error = xfs_bmap_count_blocks(tp, tip, XFS_ATTR_FORK, |
264 | &taforkblks); | 264 | &taforkblks); |
265 | if (error) { | 265 | if (error) |
266 | xfs_trans_cancel(tp, 0); | 266 | goto out_trans_cancel; |
267 | goto error0; | ||
268 | } | ||
269 | } | 267 | } |
270 | 268 | ||
271 | /* | 269 | /* |
@@ -332,10 +330,10 @@ xfs_swap_extents( | |||
332 | 330 | ||
333 | 331 | ||
334 | IHOLD(ip); | 332 | IHOLD(ip); |
335 | xfs_trans_ijoin(tp, ip, lock_flags); | 333 | xfs_trans_ijoin(tp, ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
336 | 334 | ||
337 | IHOLD(tip); | 335 | IHOLD(tip); |
338 | xfs_trans_ijoin(tp, tip, lock_flags); | 336 | xfs_trans_ijoin(tp, tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
339 | 337 | ||
340 | xfs_trans_log_inode(tp, ip, ilf_fields); | 338 | xfs_trans_log_inode(tp, ip, ilf_fields); |
341 | xfs_trans_log_inode(tp, tip, tilf_fields); | 339 | xfs_trans_log_inode(tp, tip, tilf_fields); |
@@ -344,19 +342,19 @@ xfs_swap_extents( | |||
344 | * If this is a synchronous mount, make sure that the | 342 | * If this is a synchronous mount, make sure that the |
345 | * transaction goes to disk before returning to the user. | 343 | * transaction goes to disk before returning to the user. |
346 | */ | 344 | */ |
347 | if (mp->m_flags & XFS_MOUNT_WSYNC) { | 345 | if (mp->m_flags & XFS_MOUNT_WSYNC) |
348 | xfs_trans_set_sync(tp); | 346 | xfs_trans_set_sync(tp); |
349 | } | ||
350 | 347 | ||
351 | error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT); | 348 | error = xfs_trans_commit(tp, XFS_TRANS_SWAPEXT); |
352 | locked = 0; | ||
353 | 349 | ||
354 | error0: | 350 | out_unlock: |
355 | if (locked) { | 351 | xfs_iunlock(ip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
356 | xfs_iunlock(ip, lock_flags); | 352 | xfs_iunlock(tip, XFS_ILOCK_EXCL | XFS_IOLOCK_EXCL); |
357 | xfs_iunlock(tip, lock_flags); | 353 | out: |
358 | } | 354 | kmem_free(tempifp); |
359 | if (tempifp != NULL) | ||
360 | kmem_free(tempifp); | ||
361 | return error; | 355 | return error; |
356 | |||
357 | out_trans_cancel: | ||
358 | xfs_trans_cancel(tp, 0); | ||
359 | goto out_unlock; | ||
362 | } | 360 | } |
diff --git a/fs/xfs/xfs_dinode.h b/fs/xfs/xfs_dinode.h index 162e8726df5e..e5b153b2e6a3 100644 --- a/fs/xfs/xfs_dinode.h +++ b/fs/xfs/xfs_dinode.h | |||
@@ -103,7 +103,9 @@ typedef enum xfs_dinode_fmt { | |||
103 | /* | 103 | /* |
104 | * Inode size for given fs. | 104 | * Inode size for given fs. |
105 | */ | 105 | */ |
106 | #define XFS_LITINO(mp) ((mp)->m_litino) | 106 | #define XFS_LITINO(mp) \ |
107 | ((int)(((mp)->m_sb.sb_inodesize) - sizeof(struct xfs_dinode))) | ||
108 | |||
107 | #define XFS_BROOT_SIZE_ADJ \ | 109 | #define XFS_BROOT_SIZE_ADJ \ |
108 | (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t)) | 110 | (XFS_BTREE_LBLOCK_LEN - sizeof(xfs_bmdr_block_t)) |
109 | 111 | ||
diff --git a/fs/xfs/xfs_dir2.c b/fs/xfs/xfs_dir2.c index 1afb12278b8d..c657bec6d951 100644 --- a/fs/xfs/xfs_dir2.c +++ b/fs/xfs/xfs_dir2.c | |||
@@ -46,8 +46,6 @@ | |||
46 | 46 | ||
47 | struct xfs_name xfs_name_dotdot = {"..", 2}; | 47 | struct xfs_name xfs_name_dotdot = {"..", 2}; |
48 | 48 | ||
49 | extern const struct xfs_nameops xfs_default_nameops; | ||
50 | |||
51 | /* | 49 | /* |
52 | * ASCII case-insensitive (ie. A-Z) support for directories that was | 50 | * ASCII case-insensitive (ie. A-Z) support for directories that was |
53 | * used in IRIX. | 51 | * used in IRIX. |
diff --git a/fs/xfs/xfs_dir2_block.c b/fs/xfs/xfs_dir2_block.c index e1f0a06aaf04..ab52e9e1c1ee 100644 --- a/fs/xfs/xfs_dir2_block.c +++ b/fs/xfs/xfs_dir2_block.c | |||
@@ -448,7 +448,6 @@ xfs_dir2_block_getdents( | |||
448 | xfs_mount_t *mp; /* filesystem mount point */ | 448 | xfs_mount_t *mp; /* filesystem mount point */ |
449 | char *ptr; /* current data entry */ | 449 | char *ptr; /* current data entry */ |
450 | int wantoff; /* starting block offset */ | 450 | int wantoff; /* starting block offset */ |
451 | xfs_ino_t ino; | ||
452 | xfs_off_t cook; | 451 | xfs_off_t cook; |
453 | 452 | ||
454 | mp = dp->i_mount; | 453 | mp = dp->i_mount; |
@@ -509,16 +508,12 @@ xfs_dir2_block_getdents( | |||
509 | 508 | ||
510 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, | 509 | cook = xfs_dir2_db_off_to_dataptr(mp, mp->m_dirdatablk, |
511 | (char *)dep - (char *)block); | 510 | (char *)dep - (char *)block); |
512 | ino = be64_to_cpu(dep->inumber); | ||
513 | #if XFS_BIG_INUMS | ||
514 | ino += mp->m_inoadd; | ||
515 | #endif | ||
516 | 511 | ||
517 | /* | 512 | /* |
518 | * If it didn't fit, set the final offset to here & return. | 513 | * If it didn't fit, set the final offset to here & return. |
519 | */ | 514 | */ |
520 | if (filldir(dirent, dep->name, dep->namelen, cook & 0x7fffffff, | 515 | if (filldir(dirent, dep->name, dep->namelen, cook & 0x7fffffff, |
521 | ino, DT_UNKNOWN)) { | 516 | be64_to_cpu(dep->inumber), DT_UNKNOWN)) { |
522 | *offset = cook & 0x7fffffff; | 517 | *offset = cook & 0x7fffffff; |
523 | xfs_da_brelse(NULL, bp); | 518 | xfs_da_brelse(NULL, bp); |
524 | return 0; | 519 | return 0; |
diff --git a/fs/xfs/xfs_dir2_data.h b/fs/xfs/xfs_dir2_data.h index b816e0252739..efbc290c7fec 100644 --- a/fs/xfs/xfs_dir2_data.h +++ b/fs/xfs/xfs_dir2_data.h | |||
@@ -38,7 +38,7 @@ struct xfs_trans; | |||
38 | 38 | ||
39 | /* | 39 | /* |
40 | * Directory address space divided into sections, | 40 | * Directory address space divided into sections, |
41 | * spaces separated by 32gb. | 41 | * spaces separated by 32GB. |
42 | */ | 42 | */ |
43 | #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) | 43 | #define XFS_DIR2_SPACE_SIZE (1ULL << (32 + XFS_DIR2_DATA_ALIGN_LOG)) |
44 | #define XFS_DIR2_DATA_SPACE 0 | 44 | #define XFS_DIR2_DATA_SPACE 0 |
diff --git a/fs/xfs/xfs_dir2_leaf.c b/fs/xfs/xfs_dir2_leaf.c index ef805a374eec..fa913e459442 100644 --- a/fs/xfs/xfs_dir2_leaf.c +++ b/fs/xfs/xfs_dir2_leaf.c | |||
@@ -549,7 +549,7 @@ xfs_dir2_leaf_addname( | |||
549 | * Check the internal consistency of a leaf1 block. | 549 | * Check the internal consistency of a leaf1 block. |
550 | * Pop an assert if something is wrong. | 550 | * Pop an assert if something is wrong. |
551 | */ | 551 | */ |
552 | void | 552 | STATIC void |
553 | xfs_dir2_leaf_check( | 553 | xfs_dir2_leaf_check( |
554 | xfs_inode_t *dp, /* incore directory inode */ | 554 | xfs_inode_t *dp, /* incore directory inode */ |
555 | xfs_dabuf_t *bp) /* leaf's buffer */ | 555 | xfs_dabuf_t *bp) /* leaf's buffer */ |
@@ -780,7 +780,6 @@ xfs_dir2_leaf_getdents( | |||
780 | int ra_index; /* *map index for read-ahead */ | 780 | int ra_index; /* *map index for read-ahead */ |
781 | int ra_offset; /* map entry offset for ra */ | 781 | int ra_offset; /* map entry offset for ra */ |
782 | int ra_want; /* readahead count wanted */ | 782 | int ra_want; /* readahead count wanted */ |
783 | xfs_ino_t ino; | ||
784 | 783 | ||
785 | /* | 784 | /* |
786 | * If the offset is at or past the largest allowed value, | 785 | * If the offset is at or past the largest allowed value, |
@@ -1076,24 +1075,12 @@ xfs_dir2_leaf_getdents( | |||
1076 | continue; | 1075 | continue; |
1077 | } | 1076 | } |
1078 | 1077 | ||
1079 | /* | ||
1080 | * Copy the entry into the putargs, and try formatting it. | ||
1081 | */ | ||
1082 | dep = (xfs_dir2_data_entry_t *)ptr; | 1078 | dep = (xfs_dir2_data_entry_t *)ptr; |
1083 | |||
1084 | length = xfs_dir2_data_entsize(dep->namelen); | 1079 | length = xfs_dir2_data_entsize(dep->namelen); |
1085 | 1080 | ||
1086 | ino = be64_to_cpu(dep->inumber); | ||
1087 | #if XFS_BIG_INUMS | ||
1088 | ino += mp->m_inoadd; | ||
1089 | #endif | ||
1090 | |||
1091 | /* | ||
1092 | * Won't fit. Return to caller. | ||
1093 | */ | ||
1094 | if (filldir(dirent, dep->name, dep->namelen, | 1081 | if (filldir(dirent, dep->name, dep->namelen, |
1095 | xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff, | 1082 | xfs_dir2_byte_to_dataptr(mp, curoff) & 0x7fffffff, |
1096 | ino, DT_UNKNOWN)) | 1083 | be64_to_cpu(dep->inumber), DT_UNKNOWN)) |
1097 | break; | 1084 | break; |
1098 | 1085 | ||
1099 | /* | 1086 | /* |
diff --git a/fs/xfs/xfs_dir2_node.c b/fs/xfs/xfs_dir2_node.c index fa6c3a5ddbc6..5a81ccd1045b 100644 --- a/fs/xfs/xfs_dir2_node.c +++ b/fs/xfs/xfs_dir2_node.c | |||
@@ -1104,7 +1104,7 @@ xfs_dir2_leafn_remove( | |||
1104 | } | 1104 | } |
1105 | xfs_dir2_leafn_check(dp, bp); | 1105 | xfs_dir2_leafn_check(dp, bp); |
1106 | /* | 1106 | /* |
1107 | * Return indication of whether this leaf block is emtpy enough | 1107 | * Return indication of whether this leaf block is empty enough |
1108 | * to justify trying to join it with a neighbor. | 1108 | * to justify trying to join it with a neighbor. |
1109 | */ | 1109 | */ |
1110 | *rval = | 1110 | *rval = |
diff --git a/fs/xfs/xfs_dir2_sf.c b/fs/xfs/xfs_dir2_sf.c index a8a8a6efad5b..e89734e84646 100644 --- a/fs/xfs/xfs_dir2_sf.c +++ b/fs/xfs/xfs_dir2_sf.c | |||
@@ -748,11 +748,7 @@ xfs_dir2_sf_getdents( | |||
748 | * Put . entry unless we're starting past it. | 748 | * Put . entry unless we're starting past it. |
749 | */ | 749 | */ |
750 | if (*offset <= dot_offset) { | 750 | if (*offset <= dot_offset) { |
751 | ino = dp->i_ino; | 751 | if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, dp->i_ino, DT_DIR)) { |
752 | #if XFS_BIG_INUMS | ||
753 | ino += mp->m_inoadd; | ||
754 | #endif | ||
755 | if (filldir(dirent, ".", 1, dot_offset & 0x7fffffff, ino, DT_DIR)) { | ||
756 | *offset = dot_offset & 0x7fffffff; | 752 | *offset = dot_offset & 0x7fffffff; |
757 | return 0; | 753 | return 0; |
758 | } | 754 | } |
@@ -763,9 +759,6 @@ xfs_dir2_sf_getdents( | |||
763 | */ | 759 | */ |
764 | if (*offset <= dotdot_offset) { | 760 | if (*offset <= dotdot_offset) { |
765 | ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); | 761 | ino = xfs_dir2_sf_get_inumber(sfp, &sfp->hdr.parent); |
766 | #if XFS_BIG_INUMS | ||
767 | ino += mp->m_inoadd; | ||
768 | #endif | ||
769 | if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) { | 762 | if (filldir(dirent, "..", 2, dotdot_offset & 0x7fffffff, ino, DT_DIR)) { |
770 | *offset = dotdot_offset & 0x7fffffff; | 763 | *offset = dotdot_offset & 0x7fffffff; |
771 | return 0; | 764 | return 0; |
@@ -786,10 +779,6 @@ xfs_dir2_sf_getdents( | |||
786 | } | 779 | } |
787 | 780 | ||
788 | ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep)); | 781 | ino = xfs_dir2_sf_get_inumber(sfp, xfs_dir2_sf_inumberp(sfep)); |
789 | #if XFS_BIG_INUMS | ||
790 | ino += mp->m_inoadd; | ||
791 | #endif | ||
792 | |||
793 | if (filldir(dirent, sfep->name, sfep->namelen, | 782 | if (filldir(dirent, sfep->name, sfep->namelen, |
794 | off & 0x7fffffff, ino, DT_UNKNOWN)) { | 783 | off & 0x7fffffff, ino, DT_UNKNOWN)) { |
795 | *offset = off & 0x7fffffff; | 784 | *offset = off & 0x7fffffff; |
diff --git a/fs/xfs/xfs_extfree_item.h b/fs/xfs/xfs_extfree_item.h index 2f049f63e85f..0d22c56fdf64 100644 --- a/fs/xfs/xfs_extfree_item.h +++ b/fs/xfs/xfs_extfree_item.h | |||
@@ -33,12 +33,10 @@ typedef struct xfs_extent { | |||
33 | * conversion routine. | 33 | * conversion routine. |
34 | */ | 34 | */ |
35 | 35 | ||
36 | #ifndef HAVE_FORMAT32 | ||
37 | typedef struct xfs_extent_32 { | 36 | typedef struct xfs_extent_32 { |
38 | __uint64_t ext_start; | 37 | __uint64_t ext_start; |
39 | __uint32_t ext_len; | 38 | __uint32_t ext_len; |
40 | } __attribute__((packed)) xfs_extent_32_t; | 39 | } __attribute__((packed)) xfs_extent_32_t; |
41 | #endif | ||
42 | 40 | ||
43 | typedef struct xfs_extent_64 { | 41 | typedef struct xfs_extent_64 { |
44 | __uint64_t ext_start; | 42 | __uint64_t ext_start; |
@@ -59,7 +57,6 @@ typedef struct xfs_efi_log_format { | |||
59 | xfs_extent_t efi_extents[1]; /* array of extents to free */ | 57 | xfs_extent_t efi_extents[1]; /* array of extents to free */ |
60 | } xfs_efi_log_format_t; | 58 | } xfs_efi_log_format_t; |
61 | 59 | ||
62 | #ifndef HAVE_FORMAT32 | ||
63 | typedef struct xfs_efi_log_format_32 { | 60 | typedef struct xfs_efi_log_format_32 { |
64 | __uint16_t efi_type; /* efi log item type */ | 61 | __uint16_t efi_type; /* efi log item type */ |
65 | __uint16_t efi_size; /* size of this item */ | 62 | __uint16_t efi_size; /* size of this item */ |
@@ -67,7 +64,6 @@ typedef struct xfs_efi_log_format_32 { | |||
67 | __uint64_t efi_id; /* efi identifier */ | 64 | __uint64_t efi_id; /* efi identifier */ |
68 | xfs_extent_32_t efi_extents[1]; /* array of extents to free */ | 65 | xfs_extent_32_t efi_extents[1]; /* array of extents to free */ |
69 | } __attribute__((packed)) xfs_efi_log_format_32_t; | 66 | } __attribute__((packed)) xfs_efi_log_format_32_t; |
70 | #endif | ||
71 | 67 | ||
72 | typedef struct xfs_efi_log_format_64 { | 68 | typedef struct xfs_efi_log_format_64 { |
73 | __uint16_t efi_type; /* efi log item type */ | 69 | __uint16_t efi_type; /* efi log item type */ |
@@ -90,7 +86,6 @@ typedef struct xfs_efd_log_format { | |||
90 | xfs_extent_t efd_extents[1]; /* array of extents freed */ | 86 | xfs_extent_t efd_extents[1]; /* array of extents freed */ |
91 | } xfs_efd_log_format_t; | 87 | } xfs_efd_log_format_t; |
92 | 88 | ||
93 | #ifndef HAVE_FORMAT32 | ||
94 | typedef struct xfs_efd_log_format_32 { | 89 | typedef struct xfs_efd_log_format_32 { |
95 | __uint16_t efd_type; /* efd log item type */ | 90 | __uint16_t efd_type; /* efd log item type */ |
96 | __uint16_t efd_size; /* size of this item */ | 91 | __uint16_t efd_size; /* size of this item */ |
@@ -98,7 +93,6 @@ typedef struct xfs_efd_log_format_32 { | |||
98 | __uint64_t efd_efi_id; /* id of corresponding efi */ | 93 | __uint64_t efd_efi_id; /* id of corresponding efi */ |
99 | xfs_extent_32_t efd_extents[1]; /* array of extents freed */ | 94 | xfs_extent_32_t efd_extents[1]; /* array of extents freed */ |
100 | } __attribute__((packed)) xfs_efd_log_format_32_t; | 95 | } __attribute__((packed)) xfs_efd_log_format_32_t; |
101 | #endif | ||
102 | 96 | ||
103 | typedef struct xfs_efd_log_format_64 { | 97 | typedef struct xfs_efd_log_format_64 { |
104 | __uint16_t efd_type; /* efd log item type */ | 98 | __uint16_t efd_type; /* efd log item type */ |
diff --git a/fs/xfs/xfs_filestream.c b/fs/xfs/xfs_filestream.c index f3bb75da384e..6c87c8f304ef 100644 --- a/fs/xfs/xfs_filestream.c +++ b/fs/xfs/xfs_filestream.c | |||
@@ -140,7 +140,7 @@ _xfs_filestream_pick_ag( | |||
140 | xfs_extlen_t minlen) | 140 | xfs_extlen_t minlen) |
141 | { | 141 | { |
142 | int err, trylock, nscan; | 142 | int err, trylock, nscan; |
143 | xfs_extlen_t delta, longest, need, free, minfree, maxfree = 0; | 143 | xfs_extlen_t longest, free, minfree, maxfree = 0; |
144 | xfs_agnumber_t ag, max_ag = NULLAGNUMBER; | 144 | xfs_agnumber_t ag, max_ag = NULLAGNUMBER; |
145 | struct xfs_perag *pag; | 145 | struct xfs_perag *pag; |
146 | 146 | ||
@@ -186,12 +186,7 @@ _xfs_filestream_pick_ag( | |||
186 | goto next_ag; | 186 | goto next_ag; |
187 | } | 187 | } |
188 | 188 | ||
189 | need = XFS_MIN_FREELIST_PAG(pag, mp); | 189 | longest = xfs_alloc_longest_free_extent(mp, pag); |
190 | delta = need > pag->pagf_flcount ? need - pag->pagf_flcount : 0; | ||
191 | longest = (pag->pagf_longest > delta) ? | ||
192 | (pag->pagf_longest - delta) : | ||
193 | (pag->pagf_flcount > 0 || pag->pagf_longest > 0); | ||
194 | |||
195 | if (((minlen && longest >= minlen) || | 190 | if (((minlen && longest >= minlen) || |
196 | (!minlen && pag->pagf_freeblks >= minfree)) && | 191 | (!minlen && pag->pagf_freeblks >= minfree)) && |
197 | (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || | 192 | (!pag->pagf_metadata || !(flags & XFS_PICK_USERDATA) || |
diff --git a/fs/xfs/xfs_fsops.c b/fs/xfs/xfs_fsops.c index 680d0e0ec932..8379e3bca26c 100644 --- a/fs/xfs/xfs_fsops.c +++ b/fs/xfs/xfs_fsops.c | |||
@@ -576,7 +576,7 @@ out: | |||
576 | if (fdblks_delta) { | 576 | if (fdblks_delta) { |
577 | /* | 577 | /* |
578 | * If we are putting blocks back here, m_resblks_avail is | 578 | * If we are putting blocks back here, m_resblks_avail is |
579 | * already at it's max so this will put it in the free pool. | 579 | * already at its max so this will put it in the free pool. |
580 | * | 580 | * |
581 | * If we need space, we'll either succeed in getting it | 581 | * If we need space, we'll either succeed in getting it |
582 | * from the free block count or we'll get an enospc. If | 582 | * from the free block count or we'll get an enospc. If |
diff --git a/fs/xfs/xfs_ialloc.c b/fs/xfs/xfs_ialloc.c index ab016e5ae7be..3120a3a5e20f 100644 --- a/fs/xfs/xfs_ialloc.c +++ b/fs/xfs/xfs_ialloc.c | |||
@@ -230,7 +230,7 @@ xfs_ialloc_ag_alloc( | |||
230 | args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1; | 230 | args.minalignslop = xfs_ialloc_cluster_alignment(&args) - 1; |
231 | 231 | ||
232 | /* Allow space for the inode btree to split. */ | 232 | /* Allow space for the inode btree to split. */ |
233 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; | 233 | args.minleft = args.mp->m_in_maxlevels - 1; |
234 | if ((error = xfs_alloc_vextent(&args))) | 234 | if ((error = xfs_alloc_vextent(&args))) |
235 | return error; | 235 | return error; |
236 | } else | 236 | } else |
@@ -270,7 +270,7 @@ xfs_ialloc_ag_alloc( | |||
270 | /* | 270 | /* |
271 | * Allow space for the inode btree to split. | 271 | * Allow space for the inode btree to split. |
272 | */ | 272 | */ |
273 | args.minleft = XFS_IN_MAXLEVELS(args.mp) - 1; | 273 | args.minleft = args.mp->m_in_maxlevels - 1; |
274 | if ((error = xfs_alloc_vextent(&args))) | 274 | if ((error = xfs_alloc_vextent(&args))) |
275 | return error; | 275 | return error; |
276 | } | 276 | } |
@@ -349,7 +349,7 @@ xfs_ialloc_ag_alloc( | |||
349 | * Initialize all inodes in this buffer and then log them. | 349 | * Initialize all inodes in this buffer and then log them. |
350 | * | 350 | * |
351 | * XXX: It would be much better if we had just one transaction to | 351 | * XXX: It would be much better if we had just one transaction to |
352 | * log a whole cluster of inodes instead of all the indivdual | 352 | * log a whole cluster of inodes instead of all the individual |
353 | * transactions causing a lot of log traffic. | 353 | * transactions causing a lot of log traffic. |
354 | */ | 354 | */ |
355 | xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog); | 355 | xfs_biozero(fbuf, 0, ninodes << args.mp->m_sb.sb_inodelog); |
@@ -943,7 +943,7 @@ nextag: | |||
943 | ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % | 943 | ASSERT((XFS_AGINO_TO_OFFSET(mp, rec.ir_startino) % |
944 | XFS_INODES_PER_CHUNK) == 0); | 944 | XFS_INODES_PER_CHUNK) == 0); |
945 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); | 945 | ino = XFS_AGINO_TO_INO(mp, agno, rec.ir_startino + offset); |
946 | XFS_INOBT_CLR_FREE(&rec, offset); | 946 | rec.ir_free &= ~XFS_INOBT_MASK(offset); |
947 | rec.ir_freecount--; | 947 | rec.ir_freecount--; |
948 | if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, | 948 | if ((error = xfs_inobt_update(cur, rec.ir_startino, rec.ir_freecount, |
949 | rec.ir_free))) | 949 | rec.ir_free))) |
@@ -1105,11 +1105,11 @@ xfs_difree( | |||
1105 | */ | 1105 | */ |
1106 | off = agino - rec.ir_startino; | 1106 | off = agino - rec.ir_startino; |
1107 | ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK); | 1107 | ASSERT(off >= 0 && off < XFS_INODES_PER_CHUNK); |
1108 | ASSERT(!XFS_INOBT_IS_FREE(&rec, off)); | 1108 | ASSERT(!(rec.ir_free & XFS_INOBT_MASK(off))); |
1109 | /* | 1109 | /* |
1110 | * Mark the inode free & increment the count. | 1110 | * Mark the inode free & increment the count. |
1111 | */ | 1111 | */ |
1112 | XFS_INOBT_SET_FREE(&rec, off); | 1112 | rec.ir_free |= XFS_INOBT_MASK(off); |
1113 | rec.ir_freecount++; | 1113 | rec.ir_freecount++; |
1114 | 1114 | ||
1115 | /* | 1115 | /* |
diff --git a/fs/xfs/xfs_ialloc_btree.c b/fs/xfs/xfs_ialloc_btree.c index 99f2408e8d8e..c282a9af5393 100644 --- a/fs/xfs/xfs_ialloc_btree.c +++ b/fs/xfs/xfs_ialloc_btree.c | |||
@@ -164,7 +164,7 @@ xfs_inobt_init_rec_from_cur( | |||
164 | } | 164 | } |
165 | 165 | ||
166 | /* | 166 | /* |
167 | * intial value of ptr for lookup | 167 | * initial value of ptr for lookup |
168 | */ | 168 | */ |
169 | STATIC void | 169 | STATIC void |
170 | xfs_inobt_init_ptr_from_cur( | 170 | xfs_inobt_init_ptr_from_cur( |
diff --git a/fs/xfs/xfs_ialloc_btree.h b/fs/xfs/xfs_ialloc_btree.h index 5580e255ff06..f782ad0c4769 100644 --- a/fs/xfs/xfs_ialloc_btree.h +++ b/fs/xfs/xfs_ialloc_btree.h | |||
@@ -32,14 +32,14 @@ struct xfs_mount; | |||
32 | #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ | 32 | #define XFS_IBT_MAGIC 0x49414254 /* 'IABT' */ |
33 | 33 | ||
34 | typedef __uint64_t xfs_inofree_t; | 34 | typedef __uint64_t xfs_inofree_t; |
35 | #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) | 35 | #define XFS_INODES_PER_CHUNK (NBBY * sizeof(xfs_inofree_t)) |
36 | #define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) | 36 | #define XFS_INODES_PER_CHUNK_LOG (XFS_NBBYLOG + 3) |
37 | #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) | 37 | #define XFS_INOBT_ALL_FREE ((xfs_inofree_t)-1) |
38 | #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) | ||
38 | 39 | ||
39 | static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) | 40 | static inline xfs_inofree_t xfs_inobt_maskn(int i, int n) |
40 | { | 41 | { |
41 | return (((n) >= XFS_INODES_PER_CHUNK ? \ | 42 | return ((n >= XFS_INODES_PER_CHUNK ? 0 : XFS_INOBT_MASK(n)) - 1) << i; |
42 | (xfs_inofree_t)0 : ((xfs_inofree_t)1 << (n))) - 1) << (i); | ||
43 | } | 43 | } |
44 | 44 | ||
45 | /* | 45 | /* |
@@ -69,20 +69,6 @@ typedef struct xfs_inobt_key { | |||
69 | typedef __be32 xfs_inobt_ptr_t; | 69 | typedef __be32 xfs_inobt_ptr_t; |
70 | 70 | ||
71 | /* | 71 | /* |
72 | * Bit manipulations for ir_free. | ||
73 | */ | ||
74 | #define XFS_INOBT_MASK(i) ((xfs_inofree_t)1 << (i)) | ||
75 | #define XFS_INOBT_IS_FREE(rp,i) \ | ||
76 | (((rp)->ir_free & XFS_INOBT_MASK(i)) != 0) | ||
77 | #define XFS_INOBT_SET_FREE(rp,i) ((rp)->ir_free |= XFS_INOBT_MASK(i)) | ||
78 | #define XFS_INOBT_CLR_FREE(rp,i) ((rp)->ir_free &= ~XFS_INOBT_MASK(i)) | ||
79 | |||
80 | /* | ||
81 | * Maximum number of inode btree levels. | ||
82 | */ | ||
83 | #define XFS_IN_MAXLEVELS(mp) ((mp)->m_in_maxlevels) | ||
84 | |||
85 | /* | ||
86 | * block numbers in the AG. | 72 | * block numbers in the AG. |
87 | */ | 73 | */ |
88 | #define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) | 74 | #define XFS_IBT_BLOCK(mp) ((xfs_agblock_t)(XFS_CNT_BLOCK(mp) + 1)) |
diff --git a/fs/xfs/xfs_inode.h b/fs/xfs/xfs_inode.h index 1f175fa34b22..f879c1bc4b96 100644 --- a/fs/xfs/xfs_inode.h +++ b/fs/xfs/xfs_inode.h | |||
@@ -122,7 +122,7 @@ typedef struct xfs_ictimestamp { | |||
122 | 122 | ||
123 | /* | 123 | /* |
124 | * NOTE: This structure must be kept identical to struct xfs_dinode | 124 | * NOTE: This structure must be kept identical to struct xfs_dinode |
125 | * in xfs_dinode.h except for the endianess annotations. | 125 | * in xfs_dinode.h except for the endianness annotations. |
126 | */ | 126 | */ |
127 | typedef struct xfs_icdinode { | 127 | typedef struct xfs_icdinode { |
128 | __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ | 128 | __uint16_t di_magic; /* inode magic # = XFS_DINODE_MAGIC */ |
diff --git a/fs/xfs/xfs_inode_item.h b/fs/xfs/xfs_inode_item.h index 9957d0602d54..a52ac125f055 100644 --- a/fs/xfs/xfs_inode_item.h +++ b/fs/xfs/xfs_inode_item.h | |||
@@ -40,7 +40,6 @@ typedef struct xfs_inode_log_format { | |||
40 | __int32_t ilf_boffset; /* off of inode in buffer */ | 40 | __int32_t ilf_boffset; /* off of inode in buffer */ |
41 | } xfs_inode_log_format_t; | 41 | } xfs_inode_log_format_t; |
42 | 42 | ||
43 | #ifndef HAVE_FORMAT32 | ||
44 | typedef struct xfs_inode_log_format_32 { | 43 | typedef struct xfs_inode_log_format_32 { |
45 | __uint16_t ilf_type; /* inode log item type */ | 44 | __uint16_t ilf_type; /* inode log item type */ |
46 | __uint16_t ilf_size; /* size of this item */ | 45 | __uint16_t ilf_size; /* size of this item */ |
@@ -56,7 +55,6 @@ typedef struct xfs_inode_log_format_32 { | |||
56 | __int32_t ilf_len; /* len of inode buffer */ | 55 | __int32_t ilf_len; /* len of inode buffer */ |
57 | __int32_t ilf_boffset; /* off of inode in buffer */ | 56 | __int32_t ilf_boffset; /* off of inode in buffer */ |
58 | } __attribute__((packed)) xfs_inode_log_format_32_t; | 57 | } __attribute__((packed)) xfs_inode_log_format_32_t; |
59 | #endif | ||
60 | 58 | ||
61 | typedef struct xfs_inode_log_format_64 { | 59 | typedef struct xfs_inode_log_format_64 { |
62 | __uint16_t ilf_type; /* inode log item type */ | 60 | __uint16_t ilf_type; /* inode log item type */ |
diff --git a/fs/xfs/xfs_iomap.h b/fs/xfs/xfs_iomap.h index ee1a0c134cc2..a1cc1322fc0f 100644 --- a/fs/xfs/xfs_iomap.h +++ b/fs/xfs/xfs_iomap.h | |||
@@ -63,7 +63,7 @@ typedef enum { | |||
63 | */ | 63 | */ |
64 | 64 | ||
65 | typedef struct xfs_iomap { | 65 | typedef struct xfs_iomap { |
66 | xfs_daddr_t iomap_bn; /* first 512b blk of mapping */ | 66 | xfs_daddr_t iomap_bn; /* first 512B blk of mapping */ |
67 | xfs_buftarg_t *iomap_target; | 67 | xfs_buftarg_t *iomap_target; |
68 | xfs_off_t iomap_offset; /* offset of mapping, bytes */ | 68 | xfs_off_t iomap_offset; /* offset of mapping, bytes */ |
69 | xfs_off_t iomap_bsize; /* size of mapping, bytes */ | 69 | xfs_off_t iomap_bsize; /* size of mapping, bytes */ |
diff --git a/fs/xfs/xfs_itable.c b/fs/xfs/xfs_itable.c index cf98a805ec90..aeb2d2221c7d 100644 --- a/fs/xfs/xfs_itable.c +++ b/fs/xfs/xfs_itable.c | |||
@@ -83,7 +83,12 @@ xfs_bulkstat_one_iget( | |||
83 | buf->bs_uid = dic->di_uid; | 83 | buf->bs_uid = dic->di_uid; |
84 | buf->bs_gid = dic->di_gid; | 84 | buf->bs_gid = dic->di_gid; |
85 | buf->bs_size = dic->di_size; | 85 | buf->bs_size = dic->di_size; |
86 | vn_atime_to_bstime(VFS_I(ip), &buf->bs_atime); | 86 | /* |
87 | * We are reading the atime from the Linux inode because the | ||
88 | * dinode might not be uptodate. | ||
89 | */ | ||
90 | buf->bs_atime.tv_sec = VFS_I(ip)->i_atime.tv_sec; | ||
91 | buf->bs_atime.tv_nsec = VFS_I(ip)->i_atime.tv_nsec; | ||
87 | buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; | 92 | buf->bs_mtime.tv_sec = dic->di_mtime.t_sec; |
88 | buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; | 93 | buf->bs_mtime.tv_nsec = dic->di_mtime.t_nsec; |
89 | buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; | 94 | buf->bs_ctime.tv_sec = dic->di_ctime.t_sec; |
@@ -579,7 +584,7 @@ xfs_bulkstat( | |||
579 | * first inode of the cluster. | 584 | * first inode of the cluster. |
580 | * | 585 | * |
581 | * Careful with clustidx. There can be | 586 | * Careful with clustidx. There can be |
582 | * multple clusters per chunk, a single | 587 | * multiple clusters per chunk, a single |
583 | * cluster per chunk or a cluster that has | 588 | * cluster per chunk or a cluster that has |
584 | * inodes represented from several different | 589 | * inodes represented from several different |
585 | * chunks (if blocksize is large). | 590 | * chunks (if blocksize is large). |
diff --git a/fs/xfs/xfs_log.c b/fs/xfs/xfs_log.c index f4726f702a9e..f76c6d7cea21 100644 --- a/fs/xfs/xfs_log.c +++ b/fs/xfs/xfs_log.c | |||
@@ -574,7 +574,7 @@ xfs_log_mount( | |||
574 | error = xfs_trans_ail_init(mp); | 574 | error = xfs_trans_ail_init(mp); |
575 | if (error) { | 575 | if (error) { |
576 | cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); | 576 | cmn_err(CE_WARN, "XFS: AIL initialisation failed: error %d", error); |
577 | goto error; | 577 | goto out_free_log; |
578 | } | 578 | } |
579 | mp->m_log->l_ailp = mp->m_ail; | 579 | mp->m_log->l_ailp = mp->m_ail; |
580 | 580 | ||
@@ -594,20 +594,22 @@ xfs_log_mount( | |||
594 | mp->m_flags |= XFS_MOUNT_RDONLY; | 594 | mp->m_flags |= XFS_MOUNT_RDONLY; |
595 | if (error) { | 595 | if (error) { |
596 | cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); | 596 | cmn_err(CE_WARN, "XFS: log mount/recovery failed: error %d", error); |
597 | goto error; | 597 | goto out_destroy_ail; |
598 | } | 598 | } |
599 | } | 599 | } |
600 | 600 | ||
601 | /* Normal transactions can now occur */ | 601 | /* Normal transactions can now occur */ |
602 | mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY; | 602 | mp->m_log->l_flags &= ~XLOG_ACTIVE_RECOVERY; |
603 | 603 | ||
604 | /* End mounting message in xfs_log_mount_finish */ | ||
605 | return 0; | 604 | return 0; |
606 | error: | 605 | |
607 | xfs_log_unmount_dealloc(mp); | 606 | out_destroy_ail: |
607 | xfs_trans_ail_destroy(mp); | ||
608 | out_free_log: | ||
609 | xlog_dealloc_log(mp->m_log); | ||
608 | out: | 610 | out: |
609 | return error; | 611 | return error; |
610 | } /* xfs_log_mount */ | 612 | } |
611 | 613 | ||
612 | /* | 614 | /* |
613 | * Finish the recovery of the file system. This is separate from | 615 | * Finish the recovery of the file system. This is separate from |
@@ -633,19 +635,6 @@ xfs_log_mount_finish(xfs_mount_t *mp) | |||
633 | } | 635 | } |
634 | 636 | ||
635 | /* | 637 | /* |
636 | * Unmount processing for the log. | ||
637 | */ | ||
638 | int | ||
639 | xfs_log_unmount(xfs_mount_t *mp) | ||
640 | { | ||
641 | int error; | ||
642 | |||
643 | error = xfs_log_unmount_write(mp); | ||
644 | xfs_log_unmount_dealloc(mp); | ||
645 | return error; | ||
646 | } | ||
647 | |||
648 | /* | ||
649 | * Final log writes as part of unmount. | 638 | * Final log writes as part of unmount. |
650 | * | 639 | * |
651 | * Mark the filesystem clean as unmount happens. Note that during relocation | 640 | * Mark the filesystem clean as unmount happens. Note that during relocation |
@@ -795,7 +784,7 @@ xfs_log_unmount_write(xfs_mount_t *mp) | |||
795 | * and deallocate the log as the aild references the log. | 784 | * and deallocate the log as the aild references the log. |
796 | */ | 785 | */ |
797 | void | 786 | void |
798 | xfs_log_unmount_dealloc(xfs_mount_t *mp) | 787 | xfs_log_unmount(xfs_mount_t *mp) |
799 | { | 788 | { |
800 | xfs_trans_ail_destroy(mp); | 789 | xfs_trans_ail_destroy(mp); |
801 | xlog_dealloc_log(mp->m_log); | 790 | xlog_dealloc_log(mp->m_log); |
@@ -1109,7 +1098,7 @@ xlog_bdstrat_cb(struct xfs_buf *bp) | |||
1109 | /* | 1098 | /* |
1110 | * Return size of each in-core log record buffer. | 1099 | * Return size of each in-core log record buffer. |
1111 | * | 1100 | * |
1112 | * All machines get 8 x 32KB buffers by default, unless tuned otherwise. | 1101 | * All machines get 8 x 32kB buffers by default, unless tuned otherwise. |
1113 | * | 1102 | * |
1114 | * If the filesystem blocksize is too large, we may need to choose a | 1103 | * If the filesystem blocksize is too large, we may need to choose a |
1115 | * larger size since the directory code currently logs entire blocks. | 1104 | * larger size since the directory code currently logs entire blocks. |
@@ -1139,8 +1128,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
1139 | } | 1128 | } |
1140 | 1129 | ||
1141 | if (xfs_sb_version_haslogv2(&mp->m_sb)) { | 1130 | if (xfs_sb_version_haslogv2(&mp->m_sb)) { |
1142 | /* # headers = size / 32K | 1131 | /* # headers = size / 32k |
1143 | * one header holds cycles from 32K of data | 1132 | * one header holds cycles from 32k of data |
1144 | */ | 1133 | */ |
1145 | 1134 | ||
1146 | xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE; | 1135 | xhdrs = mp->m_logbsize / XLOG_HEADER_CYCLE_SIZE; |
@@ -1156,7 +1145,7 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
1156 | goto done; | 1145 | goto done; |
1157 | } | 1146 | } |
1158 | 1147 | ||
1159 | /* All machines use 32KB buffers by default. */ | 1148 | /* All machines use 32kB buffers by default. */ |
1160 | log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; | 1149 | log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; |
1161 | log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT; | 1150 | log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT; |
1162 | 1151 | ||
@@ -1164,32 +1153,8 @@ xlog_get_iclog_buffer_size(xfs_mount_t *mp, | |||
1164 | log->l_iclog_hsize = BBSIZE; | 1153 | log->l_iclog_hsize = BBSIZE; |
1165 | log->l_iclog_heads = 1; | 1154 | log->l_iclog_heads = 1; |
1166 | 1155 | ||
1167 | /* | 1156 | done: |
1168 | * For 16KB, we use 3 32KB buffers. For 32KB block sizes, we use | 1157 | /* are we being asked to make the sizes selected above visible? */ |
1169 | * 4 32KB buffers. For 64KB block sizes, we use 8 32KB buffers. | ||
1170 | */ | ||
1171 | if (mp->m_sb.sb_blocksize >= 16*1024) { | ||
1172 | log->l_iclog_size = XLOG_BIG_RECORD_BSIZE; | ||
1173 | log->l_iclog_size_log = XLOG_BIG_RECORD_BSHIFT; | ||
1174 | if (mp->m_logbufs <= 0) { | ||
1175 | switch (mp->m_sb.sb_blocksize) { | ||
1176 | case 16*1024: /* 16 KB */ | ||
1177 | log->l_iclog_bufs = 3; | ||
1178 | break; | ||
1179 | case 32*1024: /* 32 KB */ | ||
1180 | log->l_iclog_bufs = 4; | ||
1181 | break; | ||
1182 | case 64*1024: /* 64 KB */ | ||
1183 | log->l_iclog_bufs = 8; | ||
1184 | break; | ||
1185 | default: | ||
1186 | xlog_panic("XFS: Invalid blocksize"); | ||
1187 | break; | ||
1188 | } | ||
1189 | } | ||
1190 | } | ||
1191 | |||
1192 | done: /* are we being asked to make the sizes selected above visible? */ | ||
1193 | if (mp->m_logbufs == 0) | 1158 | if (mp->m_logbufs == 0) |
1194 | mp->m_logbufs = log->l_iclog_bufs; | 1159 | mp->m_logbufs = log->l_iclog_bufs; |
1195 | if (mp->m_logbsize == 0) | 1160 | if (mp->m_logbsize == 0) |
@@ -3214,7 +3179,7 @@ xlog_state_want_sync(xlog_t *log, xlog_in_core_t *iclog) | |||
3214 | */ | 3179 | */ |
3215 | 3180 | ||
3216 | /* | 3181 | /* |
3217 | * Free a used ticket when it's refcount falls to zero. | 3182 | * Free a used ticket when its refcount falls to zero. |
3218 | */ | 3183 | */ |
3219 | void | 3184 | void |
3220 | xfs_log_ticket_put( | 3185 | xfs_log_ticket_put( |
diff --git a/fs/xfs/xfs_log.h b/fs/xfs/xfs_log.h index 8a3e84e900a3..d0c9baa50b1a 100644 --- a/fs/xfs/xfs_log.h +++ b/fs/xfs/xfs_log.h | |||
@@ -170,9 +170,8 @@ int xfs_log_write(struct xfs_mount *mp, | |||
170 | int nentries, | 170 | int nentries, |
171 | xfs_log_ticket_t ticket, | 171 | xfs_log_ticket_t ticket, |
172 | xfs_lsn_t *start_lsn); | 172 | xfs_lsn_t *start_lsn); |
173 | int xfs_log_unmount(struct xfs_mount *mp); | ||
174 | int xfs_log_unmount_write(struct xfs_mount *mp); | 173 | int xfs_log_unmount_write(struct xfs_mount *mp); |
175 | void xfs_log_unmount_dealloc(struct xfs_mount *mp); | 174 | void xfs_log_unmount(struct xfs_mount *mp); |
176 | int xfs_log_force_umount(struct xfs_mount *mp, int logerror); | 175 | int xfs_log_force_umount(struct xfs_mount *mp, int logerror); |
177 | int xfs_log_need_covered(struct xfs_mount *mp); | 176 | int xfs_log_need_covered(struct xfs_mount *mp); |
178 | 177 | ||
diff --git a/fs/xfs/xfs_log_priv.h b/fs/xfs/xfs_log_priv.h index 654167be0efb..bcad5f4c1fd1 100644 --- a/fs/xfs/xfs_log_priv.h +++ b/fs/xfs/xfs_log_priv.h | |||
@@ -359,7 +359,7 @@ typedef struct xlog_in_core { | |||
359 | int ic_size; | 359 | int ic_size; |
360 | int ic_offset; | 360 | int ic_offset; |
361 | int ic_bwritecnt; | 361 | int ic_bwritecnt; |
362 | ushort_t ic_state; | 362 | unsigned short ic_state; |
363 | char *ic_datap; /* pointer to iclog data */ | 363 | char *ic_datap; /* pointer to iclog data */ |
364 | #ifdef XFS_LOG_TRACE | 364 | #ifdef XFS_LOG_TRACE |
365 | struct ktrace *ic_trace; | 365 | struct ktrace *ic_trace; |
@@ -455,7 +455,6 @@ extern void xlog_recover_process_iunlinks(xlog_t *log); | |||
455 | 455 | ||
456 | extern struct xfs_buf *xlog_get_bp(xlog_t *, int); | 456 | extern struct xfs_buf *xlog_get_bp(xlog_t *, int); |
457 | extern void xlog_put_bp(struct xfs_buf *); | 457 | extern void xlog_put_bp(struct xfs_buf *); |
458 | extern int xlog_bread(xlog_t *, xfs_daddr_t, int, struct xfs_buf *); | ||
459 | 458 | ||
460 | extern kmem_zone_t *xfs_log_ticket_zone; | 459 | extern kmem_zone_t *xfs_log_ticket_zone; |
461 | 460 | ||
diff --git a/fs/xfs/xfs_log_recover.c b/fs/xfs/xfs_log_recover.c index 61af610d79b3..7ba450116d4f 100644 --- a/fs/xfs/xfs_log_recover.c +++ b/fs/xfs/xfs_log_recover.c | |||
@@ -94,12 +94,30 @@ xlog_put_bp( | |||
94 | xfs_buf_free(bp); | 94 | xfs_buf_free(bp); |
95 | } | 95 | } |
96 | 96 | ||
97 | STATIC xfs_caddr_t | ||
98 | xlog_align( | ||
99 | xlog_t *log, | ||
100 | xfs_daddr_t blk_no, | ||
101 | int nbblks, | ||
102 | xfs_buf_t *bp) | ||
103 | { | ||
104 | xfs_caddr_t ptr; | ||
105 | |||
106 | if (!log->l_sectbb_log) | ||
107 | return XFS_BUF_PTR(bp); | ||
108 | |||
109 | ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask); | ||
110 | ASSERT(XFS_BUF_SIZE(bp) >= | ||
111 | BBTOB(nbblks + (blk_no & log->l_sectbb_mask))); | ||
112 | return ptr; | ||
113 | } | ||
114 | |||
97 | 115 | ||
98 | /* | 116 | /* |
99 | * nbblks should be uint, but oh well. Just want to catch that 32-bit length. | 117 | * nbblks should be uint, but oh well. Just want to catch that 32-bit length. |
100 | */ | 118 | */ |
101 | int | 119 | STATIC int |
102 | xlog_bread( | 120 | xlog_bread_noalign( |
103 | xlog_t *log, | 121 | xlog_t *log, |
104 | xfs_daddr_t blk_no, | 122 | xfs_daddr_t blk_no, |
105 | int nbblks, | 123 | int nbblks, |
@@ -137,6 +155,24 @@ xlog_bread( | |||
137 | return error; | 155 | return error; |
138 | } | 156 | } |
139 | 157 | ||
158 | STATIC int | ||
159 | xlog_bread( | ||
160 | xlog_t *log, | ||
161 | xfs_daddr_t blk_no, | ||
162 | int nbblks, | ||
163 | xfs_buf_t *bp, | ||
164 | xfs_caddr_t *offset) | ||
165 | { | ||
166 | int error; | ||
167 | |||
168 | error = xlog_bread_noalign(log, blk_no, nbblks, bp); | ||
169 | if (error) | ||
170 | return error; | ||
171 | |||
172 | *offset = xlog_align(log, blk_no, nbblks, bp); | ||
173 | return 0; | ||
174 | } | ||
175 | |||
140 | /* | 176 | /* |
141 | * Write out the buffer at the given block for the given number of blocks. | 177 | * Write out the buffer at the given block for the given number of blocks. |
142 | * The buffer is kept locked across the write and is returned locked. | 178 | * The buffer is kept locked across the write and is returned locked. |
@@ -180,24 +216,6 @@ xlog_bwrite( | |||
180 | return error; | 216 | return error; |
181 | } | 217 | } |
182 | 218 | ||
183 | STATIC xfs_caddr_t | ||
184 | xlog_align( | ||
185 | xlog_t *log, | ||
186 | xfs_daddr_t blk_no, | ||
187 | int nbblks, | ||
188 | xfs_buf_t *bp) | ||
189 | { | ||
190 | xfs_caddr_t ptr; | ||
191 | |||
192 | if (!log->l_sectbb_log) | ||
193 | return XFS_BUF_PTR(bp); | ||
194 | |||
195 | ptr = XFS_BUF_PTR(bp) + BBTOB((int)blk_no & log->l_sectbb_mask); | ||
196 | ASSERT(XFS_BUF_SIZE(bp) >= | ||
197 | BBTOB(nbblks + (blk_no & log->l_sectbb_mask))); | ||
198 | return ptr; | ||
199 | } | ||
200 | |||
201 | #ifdef DEBUG | 219 | #ifdef DEBUG |
202 | /* | 220 | /* |
203 | * dump debug superblock and log record information | 221 | * dump debug superblock and log record information |
@@ -211,11 +229,11 @@ xlog_header_check_dump( | |||
211 | 229 | ||
212 | cmn_err(CE_DEBUG, "%s: SB : uuid = ", __func__); | 230 | cmn_err(CE_DEBUG, "%s: SB : uuid = ", __func__); |
213 | for (b = 0; b < 16; b++) | 231 | for (b = 0; b < 16; b++) |
214 | cmn_err(CE_DEBUG, "%02x", ((uchar_t *)&mp->m_sb.sb_uuid)[b]); | 232 | cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&mp->m_sb.sb_uuid)[b]); |
215 | cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT); | 233 | cmn_err(CE_DEBUG, ", fmt = %d\n", XLOG_FMT); |
216 | cmn_err(CE_DEBUG, " log : uuid = "); | 234 | cmn_err(CE_DEBUG, " log : uuid = "); |
217 | for (b = 0; b < 16; b++) | 235 | for (b = 0; b < 16; b++) |
218 | cmn_err(CE_DEBUG, "%02x",((uchar_t *)&head->h_fs_uuid)[b]); | 236 | cmn_err(CE_DEBUG, "%02x", ((__uint8_t *)&head->h_fs_uuid)[b]); |
219 | cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt)); | 237 | cmn_err(CE_DEBUG, ", fmt = %d\n", be32_to_cpu(head->h_fmt)); |
220 | } | 238 | } |
221 | #else | 239 | #else |
@@ -321,9 +339,9 @@ xlog_find_cycle_start( | |||
321 | 339 | ||
322 | mid_blk = BLK_AVG(first_blk, *last_blk); | 340 | mid_blk = BLK_AVG(first_blk, *last_blk); |
323 | while (mid_blk != first_blk && mid_blk != *last_blk) { | 341 | while (mid_blk != first_blk && mid_blk != *last_blk) { |
324 | if ((error = xlog_bread(log, mid_blk, 1, bp))) | 342 | error = xlog_bread(log, mid_blk, 1, bp, &offset); |
343 | if (error) | ||
325 | return error; | 344 | return error; |
326 | offset = xlog_align(log, mid_blk, 1, bp); | ||
327 | mid_cycle = xlog_get_cycle(offset); | 345 | mid_cycle = xlog_get_cycle(offset); |
328 | if (mid_cycle == cycle) { | 346 | if (mid_cycle == cycle) { |
329 | *last_blk = mid_blk; | 347 | *last_blk = mid_blk; |
@@ -379,10 +397,10 @@ xlog_find_verify_cycle( | |||
379 | 397 | ||
380 | bcount = min(bufblks, (start_blk + nbblks - i)); | 398 | bcount = min(bufblks, (start_blk + nbblks - i)); |
381 | 399 | ||
382 | if ((error = xlog_bread(log, i, bcount, bp))) | 400 | error = xlog_bread(log, i, bcount, bp, &buf); |
401 | if (error) | ||
383 | goto out; | 402 | goto out; |
384 | 403 | ||
385 | buf = xlog_align(log, i, bcount, bp); | ||
386 | for (j = 0; j < bcount; j++) { | 404 | for (j = 0; j < bcount; j++) { |
387 | cycle = xlog_get_cycle(buf); | 405 | cycle = xlog_get_cycle(buf); |
388 | if (cycle == stop_on_cycle_no) { | 406 | if (cycle == stop_on_cycle_no) { |
@@ -436,9 +454,9 @@ xlog_find_verify_log_record( | |||
436 | return ENOMEM; | 454 | return ENOMEM; |
437 | smallmem = 1; | 455 | smallmem = 1; |
438 | } else { | 456 | } else { |
439 | if ((error = xlog_bread(log, start_blk, num_blks, bp))) | 457 | error = xlog_bread(log, start_blk, num_blks, bp, &offset); |
458 | if (error) | ||
440 | goto out; | 459 | goto out; |
441 | offset = xlog_align(log, start_blk, num_blks, bp); | ||
442 | offset += ((num_blks - 1) << BBSHIFT); | 460 | offset += ((num_blks - 1) << BBSHIFT); |
443 | } | 461 | } |
444 | 462 | ||
@@ -453,9 +471,9 @@ xlog_find_verify_log_record( | |||
453 | } | 471 | } |
454 | 472 | ||
455 | if (smallmem) { | 473 | if (smallmem) { |
456 | if ((error = xlog_bread(log, i, 1, bp))) | 474 | error = xlog_bread(log, i, 1, bp, &offset); |
475 | if (error) | ||
457 | goto out; | 476 | goto out; |
458 | offset = xlog_align(log, i, 1, bp); | ||
459 | } | 477 | } |
460 | 478 | ||
461 | head = (xlog_rec_header_t *)offset; | 479 | head = (xlog_rec_header_t *)offset; |
@@ -559,15 +577,18 @@ xlog_find_head( | |||
559 | bp = xlog_get_bp(log, 1); | 577 | bp = xlog_get_bp(log, 1); |
560 | if (!bp) | 578 | if (!bp) |
561 | return ENOMEM; | 579 | return ENOMEM; |
562 | if ((error = xlog_bread(log, 0, 1, bp))) | 580 | |
581 | error = xlog_bread(log, 0, 1, bp, &offset); | ||
582 | if (error) | ||
563 | goto bp_err; | 583 | goto bp_err; |
564 | offset = xlog_align(log, 0, 1, bp); | 584 | |
565 | first_half_cycle = xlog_get_cycle(offset); | 585 | first_half_cycle = xlog_get_cycle(offset); |
566 | 586 | ||
567 | last_blk = head_blk = log_bbnum - 1; /* get cycle # of last block */ | 587 | last_blk = head_blk = log_bbnum - 1; /* get cycle # of last block */ |
568 | if ((error = xlog_bread(log, last_blk, 1, bp))) | 588 | error = xlog_bread(log, last_blk, 1, bp, &offset); |
589 | if (error) | ||
569 | goto bp_err; | 590 | goto bp_err; |
570 | offset = xlog_align(log, last_blk, 1, bp); | 591 | |
571 | last_half_cycle = xlog_get_cycle(offset); | 592 | last_half_cycle = xlog_get_cycle(offset); |
572 | ASSERT(last_half_cycle != 0); | 593 | ASSERT(last_half_cycle != 0); |
573 | 594 | ||
@@ -817,9 +838,10 @@ xlog_find_tail( | |||
817 | if (!bp) | 838 | if (!bp) |
818 | return ENOMEM; | 839 | return ENOMEM; |
819 | if (*head_blk == 0) { /* special case */ | 840 | if (*head_blk == 0) { /* special case */ |
820 | if ((error = xlog_bread(log, 0, 1, bp))) | 841 | error = xlog_bread(log, 0, 1, bp, &offset); |
842 | if (error) | ||
821 | goto bread_err; | 843 | goto bread_err; |
822 | offset = xlog_align(log, 0, 1, bp); | 844 | |
823 | if (xlog_get_cycle(offset) == 0) { | 845 | if (xlog_get_cycle(offset) == 0) { |
824 | *tail_blk = 0; | 846 | *tail_blk = 0; |
825 | /* leave all other log inited values alone */ | 847 | /* leave all other log inited values alone */ |
@@ -832,9 +854,10 @@ xlog_find_tail( | |||
832 | */ | 854 | */ |
833 | ASSERT(*head_blk < INT_MAX); | 855 | ASSERT(*head_blk < INT_MAX); |
834 | for (i = (int)(*head_blk) - 1; i >= 0; i--) { | 856 | for (i = (int)(*head_blk) - 1; i >= 0; i--) { |
835 | if ((error = xlog_bread(log, i, 1, bp))) | 857 | error = xlog_bread(log, i, 1, bp, &offset); |
858 | if (error) | ||
836 | goto bread_err; | 859 | goto bread_err; |
837 | offset = xlog_align(log, i, 1, bp); | 860 | |
838 | if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) { | 861 | if (XLOG_HEADER_MAGIC_NUM == be32_to_cpu(*(__be32 *)offset)) { |
839 | found = 1; | 862 | found = 1; |
840 | break; | 863 | break; |
@@ -848,9 +871,10 @@ xlog_find_tail( | |||
848 | */ | 871 | */ |
849 | if (!found) { | 872 | if (!found) { |
850 | for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) { | 873 | for (i = log->l_logBBsize - 1; i >= (int)(*head_blk); i--) { |
851 | if ((error = xlog_bread(log, i, 1, bp))) | 874 | error = xlog_bread(log, i, 1, bp, &offset); |
875 | if (error) | ||
852 | goto bread_err; | 876 | goto bread_err; |
853 | offset = xlog_align(log, i, 1, bp); | 877 | |
854 | if (XLOG_HEADER_MAGIC_NUM == | 878 | if (XLOG_HEADER_MAGIC_NUM == |
855 | be32_to_cpu(*(__be32 *)offset)) { | 879 | be32_to_cpu(*(__be32 *)offset)) { |
856 | found = 2; | 880 | found = 2; |
@@ -922,10 +946,10 @@ xlog_find_tail( | |||
922 | if (*head_blk == after_umount_blk && | 946 | if (*head_blk == after_umount_blk && |
923 | be32_to_cpu(rhead->h_num_logops) == 1) { | 947 | be32_to_cpu(rhead->h_num_logops) == 1) { |
924 | umount_data_blk = (i + hblks) % log->l_logBBsize; | 948 | umount_data_blk = (i + hblks) % log->l_logBBsize; |
925 | if ((error = xlog_bread(log, umount_data_blk, 1, bp))) { | 949 | error = xlog_bread(log, umount_data_blk, 1, bp, &offset); |
950 | if (error) | ||
926 | goto bread_err; | 951 | goto bread_err; |
927 | } | 952 | |
928 | offset = xlog_align(log, umount_data_blk, 1, bp); | ||
929 | op_head = (xlog_op_header_t *)offset; | 953 | op_head = (xlog_op_header_t *)offset; |
930 | if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) { | 954 | if (op_head->oh_flags & XLOG_UNMOUNT_TRANS) { |
931 | /* | 955 | /* |
@@ -1017,9 +1041,10 @@ xlog_find_zeroed( | |||
1017 | bp = xlog_get_bp(log, 1); | 1041 | bp = xlog_get_bp(log, 1); |
1018 | if (!bp) | 1042 | if (!bp) |
1019 | return ENOMEM; | 1043 | return ENOMEM; |
1020 | if ((error = xlog_bread(log, 0, 1, bp))) | 1044 | error = xlog_bread(log, 0, 1, bp, &offset); |
1045 | if (error) | ||
1021 | goto bp_err; | 1046 | goto bp_err; |
1022 | offset = xlog_align(log, 0, 1, bp); | 1047 | |
1023 | first_cycle = xlog_get_cycle(offset); | 1048 | first_cycle = xlog_get_cycle(offset); |
1024 | if (first_cycle == 0) { /* completely zeroed log */ | 1049 | if (first_cycle == 0) { /* completely zeroed log */ |
1025 | *blk_no = 0; | 1050 | *blk_no = 0; |
@@ -1028,9 +1053,10 @@ xlog_find_zeroed( | |||
1028 | } | 1053 | } |
1029 | 1054 | ||
1030 | /* check partially zeroed log */ | 1055 | /* check partially zeroed log */ |
1031 | if ((error = xlog_bread(log, log_bbnum-1, 1, bp))) | 1056 | error = xlog_bread(log, log_bbnum-1, 1, bp, &offset); |
1057 | if (error) | ||
1032 | goto bp_err; | 1058 | goto bp_err; |
1033 | offset = xlog_align(log, log_bbnum-1, 1, bp); | 1059 | |
1034 | last_cycle = xlog_get_cycle(offset); | 1060 | last_cycle = xlog_get_cycle(offset); |
1035 | if (last_cycle != 0) { /* log completely written to */ | 1061 | if (last_cycle != 0) { /* log completely written to */ |
1036 | xlog_put_bp(bp); | 1062 | xlog_put_bp(bp); |
@@ -1152,10 +1178,10 @@ xlog_write_log_records( | |||
1152 | */ | 1178 | */ |
1153 | balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block); | 1179 | balign = XLOG_SECTOR_ROUNDDOWN_BLKNO(log, start_block); |
1154 | if (balign != start_block) { | 1180 | if (balign != start_block) { |
1155 | if ((error = xlog_bread(log, start_block, 1, bp))) { | 1181 | error = xlog_bread_noalign(log, start_block, 1, bp); |
1156 | xlog_put_bp(bp); | 1182 | if (error) |
1157 | return error; | 1183 | goto out_put_bp; |
1158 | } | 1184 | |
1159 | j = start_block - balign; | 1185 | j = start_block - balign; |
1160 | } | 1186 | } |
1161 | 1187 | ||
@@ -1175,10 +1201,14 @@ xlog_write_log_records( | |||
1175 | balign = BBTOB(ealign - start_block); | 1201 | balign = BBTOB(ealign - start_block); |
1176 | error = XFS_BUF_SET_PTR(bp, offset + balign, | 1202 | error = XFS_BUF_SET_PTR(bp, offset + balign, |
1177 | BBTOB(sectbb)); | 1203 | BBTOB(sectbb)); |
1178 | if (!error) | 1204 | if (error) |
1179 | error = xlog_bread(log, ealign, sectbb, bp); | 1205 | break; |
1180 | if (!error) | 1206 | |
1181 | error = XFS_BUF_SET_PTR(bp, offset, bufblks); | 1207 | error = xlog_bread_noalign(log, ealign, sectbb, bp); |
1208 | if (error) | ||
1209 | break; | ||
1210 | |||
1211 | error = XFS_BUF_SET_PTR(bp, offset, bufblks); | ||
1182 | if (error) | 1212 | if (error) |
1183 | break; | 1213 | break; |
1184 | } | 1214 | } |
@@ -1195,6 +1225,8 @@ xlog_write_log_records( | |||
1195 | start_block += endcount; | 1225 | start_block += endcount; |
1196 | j = 0; | 1226 | j = 0; |
1197 | } | 1227 | } |
1228 | |||
1229 | out_put_bp: | ||
1198 | xlog_put_bp(bp); | 1230 | xlog_put_bp(bp); |
1199 | return error; | 1231 | return error; |
1200 | } | 1232 | } |
@@ -2511,16 +2543,10 @@ xlog_recover_do_inode_trans( | |||
2511 | } | 2543 | } |
2512 | 2544 | ||
2513 | write_inode_buffer: | 2545 | write_inode_buffer: |
2514 | if (ITEM_TYPE(item) == XFS_LI_INODE) { | 2546 | ASSERT(bp->b_mount == NULL || bp->b_mount == mp); |
2515 | ASSERT(bp->b_mount == NULL || bp->b_mount == mp); | 2547 | bp->b_mount = mp; |
2516 | bp->b_mount = mp; | 2548 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); |
2517 | XFS_BUF_SET_IODONE_FUNC(bp, xlog_recover_iodone); | 2549 | xfs_bdwrite(mp, bp); |
2518 | xfs_bdwrite(mp, bp); | ||
2519 | } else { | ||
2520 | XFS_BUF_STALE(bp); | ||
2521 | error = xfs_bwrite(mp, bp); | ||
2522 | } | ||
2523 | |||
2524 | error: | 2550 | error: |
2525 | if (need_free) | 2551 | if (need_free) |
2526 | kmem_free(in_f); | 2552 | kmem_free(in_f); |
@@ -2769,51 +2795,48 @@ xlog_recover_do_trans( | |||
2769 | int error = 0; | 2795 | int error = 0; |
2770 | xlog_recover_item_t *item, *first_item; | 2796 | xlog_recover_item_t *item, *first_item; |
2771 | 2797 | ||
2772 | if ((error = xlog_recover_reorder_trans(trans))) | 2798 | error = xlog_recover_reorder_trans(trans); |
2799 | if (error) | ||
2773 | return error; | 2800 | return error; |
2801 | |||
2774 | first_item = item = trans->r_itemq; | 2802 | first_item = item = trans->r_itemq; |
2775 | do { | 2803 | do { |
2776 | /* | 2804 | switch (ITEM_TYPE(item)) { |
2777 | * we don't need to worry about the block number being | 2805 | case XFS_LI_BUF: |
2778 | * truncated in > 1 TB buffers because in user-land, | 2806 | error = xlog_recover_do_buffer_trans(log, item, pass); |
2779 | * we're now n32 or 64-bit so xfs_daddr_t is 64-bits so | 2807 | break; |
2780 | * the blknos will get through the user-mode buffer | 2808 | case XFS_LI_INODE: |
2781 | * cache properly. The only bad case is o32 kernels | 2809 | error = xlog_recover_do_inode_trans(log, item, pass); |
2782 | * where xfs_daddr_t is 32-bits but mount will warn us | 2810 | break; |
2783 | * off a > 1 TB filesystem before we get here. | 2811 | case XFS_LI_EFI: |
2784 | */ | 2812 | error = xlog_recover_do_efi_trans(log, item, |
2785 | if ((ITEM_TYPE(item) == XFS_LI_BUF)) { | 2813 | trans->r_lsn, pass); |
2786 | if ((error = xlog_recover_do_buffer_trans(log, item, | 2814 | break; |
2787 | pass))) | 2815 | case XFS_LI_EFD: |
2788 | break; | ||
2789 | } else if ((ITEM_TYPE(item) == XFS_LI_INODE)) { | ||
2790 | if ((error = xlog_recover_do_inode_trans(log, item, | ||
2791 | pass))) | ||
2792 | break; | ||
2793 | } else if (ITEM_TYPE(item) == XFS_LI_EFI) { | ||
2794 | if ((error = xlog_recover_do_efi_trans(log, item, trans->r_lsn, | ||
2795 | pass))) | ||
2796 | break; | ||
2797 | } else if (ITEM_TYPE(item) == XFS_LI_EFD) { | ||
2798 | xlog_recover_do_efd_trans(log, item, pass); | 2816 | xlog_recover_do_efd_trans(log, item, pass); |
2799 | } else if (ITEM_TYPE(item) == XFS_LI_DQUOT) { | 2817 | error = 0; |
2800 | if ((error = xlog_recover_do_dquot_trans(log, item, | 2818 | break; |
2801 | pass))) | 2819 | case XFS_LI_DQUOT: |
2802 | break; | 2820 | error = xlog_recover_do_dquot_trans(log, item, pass); |
2803 | } else if ((ITEM_TYPE(item) == XFS_LI_QUOTAOFF)) { | 2821 | break; |
2804 | if ((error = xlog_recover_do_quotaoff_trans(log, item, | 2822 | case XFS_LI_QUOTAOFF: |
2805 | pass))) | 2823 | error = xlog_recover_do_quotaoff_trans(log, item, |
2806 | break; | 2824 | pass); |
2807 | } else { | 2825 | break; |
2808 | xlog_warn("XFS: xlog_recover_do_trans"); | 2826 | default: |
2827 | xlog_warn( | ||
2828 | "XFS: invalid item type (%d) xlog_recover_do_trans", ITEM_TYPE(item)); | ||
2809 | ASSERT(0); | 2829 | ASSERT(0); |
2810 | error = XFS_ERROR(EIO); | 2830 | error = XFS_ERROR(EIO); |
2811 | break; | 2831 | break; |
2812 | } | 2832 | } |
2833 | |||
2834 | if (error) | ||
2835 | return error; | ||
2813 | item = item->ri_next; | 2836 | item = item->ri_next; |
2814 | } while (first_item != item); | 2837 | } while (first_item != item); |
2815 | 2838 | ||
2816 | return error; | 2839 | return 0; |
2817 | } | 2840 | } |
2818 | 2841 | ||
2819 | /* | 2842 | /* |
@@ -3490,9 +3513,11 @@ xlog_do_recovery_pass( | |||
3490 | hbp = xlog_get_bp(log, 1); | 3513 | hbp = xlog_get_bp(log, 1); |
3491 | if (!hbp) | 3514 | if (!hbp) |
3492 | return ENOMEM; | 3515 | return ENOMEM; |
3493 | if ((error = xlog_bread(log, tail_blk, 1, hbp))) | 3516 | |
3517 | error = xlog_bread(log, tail_blk, 1, hbp, &offset); | ||
3518 | if (error) | ||
3494 | goto bread_err1; | 3519 | goto bread_err1; |
3495 | offset = xlog_align(log, tail_blk, 1, hbp); | 3520 | |
3496 | rhead = (xlog_rec_header_t *)offset; | 3521 | rhead = (xlog_rec_header_t *)offset; |
3497 | error = xlog_valid_rec_header(log, rhead, tail_blk); | 3522 | error = xlog_valid_rec_header(log, rhead, tail_blk); |
3498 | if (error) | 3523 | if (error) |
@@ -3526,9 +3551,10 @@ xlog_do_recovery_pass( | |||
3526 | memset(rhash, 0, sizeof(rhash)); | 3551 | memset(rhash, 0, sizeof(rhash)); |
3527 | if (tail_blk <= head_blk) { | 3552 | if (tail_blk <= head_blk) { |
3528 | for (blk_no = tail_blk; blk_no < head_blk; ) { | 3553 | for (blk_no = tail_blk; blk_no < head_blk; ) { |
3529 | if ((error = xlog_bread(log, blk_no, hblks, hbp))) | 3554 | error = xlog_bread(log, blk_no, hblks, hbp, &offset); |
3555 | if (error) | ||
3530 | goto bread_err2; | 3556 | goto bread_err2; |
3531 | offset = xlog_align(log, blk_no, hblks, hbp); | 3557 | |
3532 | rhead = (xlog_rec_header_t *)offset; | 3558 | rhead = (xlog_rec_header_t *)offset; |
3533 | error = xlog_valid_rec_header(log, rhead, blk_no); | 3559 | error = xlog_valid_rec_header(log, rhead, blk_no); |
3534 | if (error) | 3560 | if (error) |
@@ -3536,10 +3562,11 @@ xlog_do_recovery_pass( | |||
3536 | 3562 | ||
3537 | /* blocks in data section */ | 3563 | /* blocks in data section */ |
3538 | bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); | 3564 | bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); |
3539 | error = xlog_bread(log, blk_no + hblks, bblks, dbp); | 3565 | error = xlog_bread(log, blk_no + hblks, bblks, dbp, |
3566 | &offset); | ||
3540 | if (error) | 3567 | if (error) |
3541 | goto bread_err2; | 3568 | goto bread_err2; |
3542 | offset = xlog_align(log, blk_no + hblks, bblks, dbp); | 3569 | |
3543 | xlog_unpack_data(rhead, offset, log); | 3570 | xlog_unpack_data(rhead, offset, log); |
3544 | if ((error = xlog_recover_process_data(log, | 3571 | if ((error = xlog_recover_process_data(log, |
3545 | rhash, rhead, offset, pass))) | 3572 | rhash, rhead, offset, pass))) |
@@ -3562,10 +3589,10 @@ xlog_do_recovery_pass( | |||
3562 | wrapped_hblks = 0; | 3589 | wrapped_hblks = 0; |
3563 | if (blk_no + hblks <= log->l_logBBsize) { | 3590 | if (blk_no + hblks <= log->l_logBBsize) { |
3564 | /* Read header in one read */ | 3591 | /* Read header in one read */ |
3565 | error = xlog_bread(log, blk_no, hblks, hbp); | 3592 | error = xlog_bread(log, blk_no, hblks, hbp, |
3593 | &offset); | ||
3566 | if (error) | 3594 | if (error) |
3567 | goto bread_err2; | 3595 | goto bread_err2; |
3568 | offset = xlog_align(log, blk_no, hblks, hbp); | ||
3569 | } else { | 3596 | } else { |
3570 | /* This LR is split across physical log end */ | 3597 | /* This LR is split across physical log end */ |
3571 | if (blk_no != log->l_logBBsize) { | 3598 | if (blk_no != log->l_logBBsize) { |
@@ -3573,12 +3600,13 @@ xlog_do_recovery_pass( | |||
3573 | ASSERT(blk_no <= INT_MAX); | 3600 | ASSERT(blk_no <= INT_MAX); |
3574 | split_hblks = log->l_logBBsize - (int)blk_no; | 3601 | split_hblks = log->l_logBBsize - (int)blk_no; |
3575 | ASSERT(split_hblks > 0); | 3602 | ASSERT(split_hblks > 0); |
3576 | if ((error = xlog_bread(log, blk_no, | 3603 | error = xlog_bread(log, blk_no, |
3577 | split_hblks, hbp))) | 3604 | split_hblks, hbp, |
3605 | &offset); | ||
3606 | if (error) | ||
3578 | goto bread_err2; | 3607 | goto bread_err2; |
3579 | offset = xlog_align(log, blk_no, | ||
3580 | split_hblks, hbp); | ||
3581 | } | 3608 | } |
3609 | |||
3582 | /* | 3610 | /* |
3583 | * Note: this black magic still works with | 3611 | * Note: this black magic still works with |
3584 | * large sector sizes (non-512) only because: | 3612 | * large sector sizes (non-512) only because: |
@@ -3596,14 +3624,19 @@ xlog_do_recovery_pass( | |||
3596 | error = XFS_BUF_SET_PTR(hbp, | 3624 | error = XFS_BUF_SET_PTR(hbp, |
3597 | bufaddr + BBTOB(split_hblks), | 3625 | bufaddr + BBTOB(split_hblks), |
3598 | BBTOB(hblks - split_hblks)); | 3626 | BBTOB(hblks - split_hblks)); |
3599 | if (!error) | 3627 | if (error) |
3600 | error = xlog_bread(log, 0, | 3628 | goto bread_err2; |
3601 | wrapped_hblks, hbp); | 3629 | |
3602 | if (!error) | 3630 | error = xlog_bread_noalign(log, 0, |
3603 | error = XFS_BUF_SET_PTR(hbp, bufaddr, | 3631 | wrapped_hblks, hbp); |
3632 | if (error) | ||
3633 | goto bread_err2; | ||
3634 | |||
3635 | error = XFS_BUF_SET_PTR(hbp, bufaddr, | ||
3604 | BBTOB(hblks)); | 3636 | BBTOB(hblks)); |
3605 | if (error) | 3637 | if (error) |
3606 | goto bread_err2; | 3638 | goto bread_err2; |
3639 | |||
3607 | if (!offset) | 3640 | if (!offset) |
3608 | offset = xlog_align(log, 0, | 3641 | offset = xlog_align(log, 0, |
3609 | wrapped_hblks, hbp); | 3642 | wrapped_hblks, hbp); |
@@ -3619,10 +3652,10 @@ xlog_do_recovery_pass( | |||
3619 | 3652 | ||
3620 | /* Read in data for log record */ | 3653 | /* Read in data for log record */ |
3621 | if (blk_no + bblks <= log->l_logBBsize) { | 3654 | if (blk_no + bblks <= log->l_logBBsize) { |
3622 | error = xlog_bread(log, blk_no, bblks, dbp); | 3655 | error = xlog_bread(log, blk_no, bblks, dbp, |
3656 | &offset); | ||
3623 | if (error) | 3657 | if (error) |
3624 | goto bread_err2; | 3658 | goto bread_err2; |
3625 | offset = xlog_align(log, blk_no, bblks, dbp); | ||
3626 | } else { | 3659 | } else { |
3627 | /* This log record is split across the | 3660 | /* This log record is split across the |
3628 | * physical end of log */ | 3661 | * physical end of log */ |
@@ -3636,12 +3669,13 @@ xlog_do_recovery_pass( | |||
3636 | split_bblks = | 3669 | split_bblks = |
3637 | log->l_logBBsize - (int)blk_no; | 3670 | log->l_logBBsize - (int)blk_no; |
3638 | ASSERT(split_bblks > 0); | 3671 | ASSERT(split_bblks > 0); |
3639 | if ((error = xlog_bread(log, blk_no, | 3672 | error = xlog_bread(log, blk_no, |
3640 | split_bblks, dbp))) | 3673 | split_bblks, dbp, |
3674 | &offset); | ||
3675 | if (error) | ||
3641 | goto bread_err2; | 3676 | goto bread_err2; |
3642 | offset = xlog_align(log, blk_no, | ||
3643 | split_bblks, dbp); | ||
3644 | } | 3677 | } |
3678 | |||
3645 | /* | 3679 | /* |
3646 | * Note: this black magic still works with | 3680 | * Note: this black magic still works with |
3647 | * large sector sizes (non-512) only because: | 3681 | * large sector sizes (non-512) only because: |
@@ -3658,15 +3692,19 @@ xlog_do_recovery_pass( | |||
3658 | error = XFS_BUF_SET_PTR(dbp, | 3692 | error = XFS_BUF_SET_PTR(dbp, |
3659 | bufaddr + BBTOB(split_bblks), | 3693 | bufaddr + BBTOB(split_bblks), |
3660 | BBTOB(bblks - split_bblks)); | 3694 | BBTOB(bblks - split_bblks)); |
3661 | if (!error) | ||
3662 | error = xlog_bread(log, wrapped_hblks, | ||
3663 | bblks - split_bblks, | ||
3664 | dbp); | ||
3665 | if (!error) | ||
3666 | error = XFS_BUF_SET_PTR(dbp, bufaddr, | ||
3667 | h_size); | ||
3668 | if (error) | 3695 | if (error) |
3669 | goto bread_err2; | 3696 | goto bread_err2; |
3697 | |||
3698 | error = xlog_bread_noalign(log, wrapped_hblks, | ||
3699 | bblks - split_bblks, | ||
3700 | dbp); | ||
3701 | if (error) | ||
3702 | goto bread_err2; | ||
3703 | |||
3704 | error = XFS_BUF_SET_PTR(dbp, bufaddr, h_size); | ||
3705 | if (error) | ||
3706 | goto bread_err2; | ||
3707 | |||
3670 | if (!offset) | 3708 | if (!offset) |
3671 | offset = xlog_align(log, wrapped_hblks, | 3709 | offset = xlog_align(log, wrapped_hblks, |
3672 | bblks - split_bblks, dbp); | 3710 | bblks - split_bblks, dbp); |
@@ -3683,17 +3721,21 @@ xlog_do_recovery_pass( | |||
3683 | 3721 | ||
3684 | /* read first part of physical log */ | 3722 | /* read first part of physical log */ |
3685 | while (blk_no < head_blk) { | 3723 | while (blk_no < head_blk) { |
3686 | if ((error = xlog_bread(log, blk_no, hblks, hbp))) | 3724 | error = xlog_bread(log, blk_no, hblks, hbp, &offset); |
3725 | if (error) | ||
3687 | goto bread_err2; | 3726 | goto bread_err2; |
3688 | offset = xlog_align(log, blk_no, hblks, hbp); | 3727 | |
3689 | rhead = (xlog_rec_header_t *)offset; | 3728 | rhead = (xlog_rec_header_t *)offset; |
3690 | error = xlog_valid_rec_header(log, rhead, blk_no); | 3729 | error = xlog_valid_rec_header(log, rhead, blk_no); |
3691 | if (error) | 3730 | if (error) |
3692 | goto bread_err2; | 3731 | goto bread_err2; |
3732 | |||
3693 | bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); | 3733 | bblks = (int)BTOBB(be32_to_cpu(rhead->h_len)); |
3694 | if ((error = xlog_bread(log, blk_no+hblks, bblks, dbp))) | 3734 | error = xlog_bread(log, blk_no+hblks, bblks, dbp, |
3735 | &offset); | ||
3736 | if (error) | ||
3695 | goto bread_err2; | 3737 | goto bread_err2; |
3696 | offset = xlog_align(log, blk_no+hblks, bblks, dbp); | 3738 | |
3697 | xlog_unpack_data(rhead, offset, log); | 3739 | xlog_unpack_data(rhead, offset, log); |
3698 | if ((error = xlog_recover_process_data(log, rhash, | 3740 | if ((error = xlog_recover_process_data(log, rhash, |
3699 | rhead, offset, pass))) | 3741 | rhead, offset, pass))) |
diff --git a/fs/xfs/xfs_mount.c b/fs/xfs/xfs_mount.c index 35300250e86d..b101990df027 100644 --- a/fs/xfs/xfs_mount.c +++ b/fs/xfs/xfs_mount.c | |||
@@ -45,7 +45,6 @@ | |||
45 | #include "xfs_fsops.h" | 45 | #include "xfs_fsops.h" |
46 | #include "xfs_utils.h" | 46 | #include "xfs_utils.h" |
47 | 47 | ||
48 | STATIC int xfs_uuid_mount(xfs_mount_t *); | ||
49 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); | 48 | STATIC void xfs_unmountfs_wait(xfs_mount_t *); |
50 | 49 | ||
51 | 50 | ||
@@ -121,6 +120,84 @@ static const struct { | |||
121 | { sizeof(xfs_sb_t), 0 } | 120 | { sizeof(xfs_sb_t), 0 } |
122 | }; | 121 | }; |
123 | 122 | ||
123 | static DEFINE_MUTEX(xfs_uuid_table_mutex); | ||
124 | static int xfs_uuid_table_size; | ||
125 | static uuid_t *xfs_uuid_table; | ||
126 | |||
127 | /* | ||
128 | * See if the UUID is unique among mounted XFS filesystems. | ||
129 | * Mount fails if UUID is nil or a FS with the same UUID is already mounted. | ||
130 | */ | ||
131 | STATIC int | ||
132 | xfs_uuid_mount( | ||
133 | struct xfs_mount *mp) | ||
134 | { | ||
135 | uuid_t *uuid = &mp->m_sb.sb_uuid; | ||
136 | int hole, i; | ||
137 | |||
138 | if (mp->m_flags & XFS_MOUNT_NOUUID) | ||
139 | return 0; | ||
140 | |||
141 | if (uuid_is_nil(uuid)) { | ||
142 | cmn_err(CE_WARN, | ||
143 | "XFS: Filesystem %s has nil UUID - can't mount", | ||
144 | mp->m_fsname); | ||
145 | return XFS_ERROR(EINVAL); | ||
146 | } | ||
147 | |||
148 | mutex_lock(&xfs_uuid_table_mutex); | ||
149 | for (i = 0, hole = -1; i < xfs_uuid_table_size; i++) { | ||
150 | if (uuid_is_nil(&xfs_uuid_table[i])) { | ||
151 | hole = i; | ||
152 | continue; | ||
153 | } | ||
154 | if (uuid_equal(uuid, &xfs_uuid_table[i])) | ||
155 | goto out_duplicate; | ||
156 | } | ||
157 | |||
158 | if (hole < 0) { | ||
159 | xfs_uuid_table = kmem_realloc(xfs_uuid_table, | ||
160 | (xfs_uuid_table_size + 1) * sizeof(*xfs_uuid_table), | ||
161 | xfs_uuid_table_size * sizeof(*xfs_uuid_table), | ||
162 | KM_SLEEP); | ||
163 | hole = xfs_uuid_table_size++; | ||
164 | } | ||
165 | xfs_uuid_table[hole] = *uuid; | ||
166 | mutex_unlock(&xfs_uuid_table_mutex); | ||
167 | |||
168 | return 0; | ||
169 | |||
170 | out_duplicate: | ||
171 | mutex_unlock(&xfs_uuid_table_mutex); | ||
172 | cmn_err(CE_WARN, "XFS: Filesystem %s has duplicate UUID - can't mount", | ||
173 | mp->m_fsname); | ||
174 | return XFS_ERROR(EINVAL); | ||
175 | } | ||
176 | |||
177 | STATIC void | ||
178 | xfs_uuid_unmount( | ||
179 | struct xfs_mount *mp) | ||
180 | { | ||
181 | uuid_t *uuid = &mp->m_sb.sb_uuid; | ||
182 | int i; | ||
183 | |||
184 | if (mp->m_flags & XFS_MOUNT_NOUUID) | ||
185 | return; | ||
186 | |||
187 | mutex_lock(&xfs_uuid_table_mutex); | ||
188 | for (i = 0; i < xfs_uuid_table_size; i++) { | ||
189 | if (uuid_is_nil(&xfs_uuid_table[i])) | ||
190 | continue; | ||
191 | if (!uuid_equal(uuid, &xfs_uuid_table[i])) | ||
192 | continue; | ||
193 | memset(&xfs_uuid_table[i], 0, sizeof(uuid_t)); | ||
194 | break; | ||
195 | } | ||
196 | ASSERT(i < xfs_uuid_table_size); | ||
197 | mutex_unlock(&xfs_uuid_table_mutex); | ||
198 | } | ||
199 | |||
200 | |||
124 | /* | 201 | /* |
125 | * Free up the resources associated with a mount structure. Assume that | 202 | * Free up the resources associated with a mount structure. Assume that |
126 | * the structure was initially zeroed, so we can tell which fields got | 203 | * the structure was initially zeroed, so we can tell which fields got |
@@ -256,6 +333,22 @@ xfs_mount_validate_sb( | |||
256 | return XFS_ERROR(ENOSYS); | 333 | return XFS_ERROR(ENOSYS); |
257 | } | 334 | } |
258 | 335 | ||
336 | /* | ||
337 | * Currently only very few inode sizes are supported. | ||
338 | */ | ||
339 | switch (sbp->sb_inodesize) { | ||
340 | case 256: | ||
341 | case 512: | ||
342 | case 1024: | ||
343 | case 2048: | ||
344 | break; | ||
345 | default: | ||
346 | xfs_fs_mount_cmn_err(flags, | ||
347 | "inode size of %d bytes not supported", | ||
348 | sbp->sb_inodesize); | ||
349 | return XFS_ERROR(ENOSYS); | ||
350 | } | ||
351 | |||
259 | if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || | 352 | if (xfs_sb_validate_fsb_count(sbp, sbp->sb_dblocks) || |
260 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { | 353 | xfs_sb_validate_fsb_count(sbp, sbp->sb_rblocks)) { |
261 | xfs_fs_mount_cmn_err(flags, | 354 | xfs_fs_mount_cmn_err(flags, |
@@ -574,32 +667,10 @@ xfs_mount_common(xfs_mount_t *mp, xfs_sb_t *sbp) | |||
574 | mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; | 667 | mp->m_sectbb_log = sbp->sb_sectlog - BBSHIFT; |
575 | mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; | 668 | mp->m_agno_log = xfs_highbit32(sbp->sb_agcount - 1) + 1; |
576 | mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog; | 669 | mp->m_agino_log = sbp->sb_inopblog + sbp->sb_agblklog; |
577 | mp->m_litino = sbp->sb_inodesize - sizeof(struct xfs_dinode); | ||
578 | mp->m_blockmask = sbp->sb_blocksize - 1; | 670 | mp->m_blockmask = sbp->sb_blocksize - 1; |
579 | mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; | 671 | mp->m_blockwsize = sbp->sb_blocksize >> XFS_WORDLOG; |
580 | mp->m_blockwmask = mp->m_blockwsize - 1; | 672 | mp->m_blockwmask = mp->m_blockwsize - 1; |
581 | 673 | ||
582 | /* | ||
583 | * Setup for attributes, in case they get created. | ||
584 | * This value is for inodes getting attributes for the first time, | ||
585 | * the per-inode value is for old attribute values. | ||
586 | */ | ||
587 | ASSERT(sbp->sb_inodesize >= 256 && sbp->sb_inodesize <= 2048); | ||
588 | switch (sbp->sb_inodesize) { | ||
589 | case 256: | ||
590 | mp->m_attroffset = XFS_LITINO(mp) - | ||
591 | XFS_BMDR_SPACE_CALC(MINABTPTRS); | ||
592 | break; | ||
593 | case 512: | ||
594 | case 1024: | ||
595 | case 2048: | ||
596 | mp->m_attroffset = XFS_BMDR_SPACE_CALC(6 * MINABTPTRS); | ||
597 | break; | ||
598 | default: | ||
599 | ASSERT(0); | ||
600 | } | ||
601 | ASSERT(mp->m_attroffset < XFS_LITINO(mp)); | ||
602 | |||
603 | mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); | 674 | mp->m_alloc_mxr[0] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 1); |
604 | mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); | 675 | mp->m_alloc_mxr[1] = xfs_allocbt_maxrecs(mp, sbp->sb_blocksize, 0); |
605 | mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; | 676 | mp->m_alloc_mnr[0] = mp->m_alloc_mxr[0] / 2; |
@@ -645,7 +716,7 @@ xfs_initialize_perag_data(xfs_mount_t *mp, xfs_agnumber_t agcount) | |||
645 | for (index = 0; index < agcount; index++) { | 716 | for (index = 0; index < agcount; index++) { |
646 | /* | 717 | /* |
647 | * read the agf, then the agi. This gets us | 718 | * read the agf, then the agi. This gets us |
648 | * all the inforamtion we need and populates the | 719 | * all the information we need and populates the |
649 | * per-ag structures for us. | 720 | * per-ag structures for us. |
650 | */ | 721 | */ |
651 | error = xfs_alloc_pagf_init(mp, NULL, index, 0); | 722 | error = xfs_alloc_pagf_init(mp, NULL, index, 0); |
@@ -886,8 +957,6 @@ xfs_check_sizes(xfs_mount_t *mp) | |||
886 | } | 957 | } |
887 | 958 | ||
888 | /* | 959 | /* |
889 | * xfs_mountfs | ||
890 | * | ||
891 | * This function does the following on an initial mount of a file system: | 960 | * This function does the following on an initial mount of a file system: |
892 | * - reads the superblock from disk and init the mount struct | 961 | * - reads the superblock from disk and init the mount struct |
893 | * - if we're a 32-bit kernel, do a size check on the superblock | 962 | * - if we're a 32-bit kernel, do a size check on the superblock |
@@ -905,7 +974,6 @@ xfs_mountfs( | |||
905 | xfs_inode_t *rip; | 974 | xfs_inode_t *rip; |
906 | __uint64_t resblks; | 975 | __uint64_t resblks; |
907 | uint quotamount, quotaflags; | 976 | uint quotamount, quotaflags; |
908 | int uuid_mounted = 0; | ||
909 | int error = 0; | 977 | int error = 0; |
910 | 978 | ||
911 | xfs_mount_common(mp, sbp); | 979 | xfs_mount_common(mp, sbp); |
@@ -960,7 +1028,7 @@ xfs_mountfs( | |||
960 | */ | 1028 | */ |
961 | error = xfs_update_alignment(mp); | 1029 | error = xfs_update_alignment(mp); |
962 | if (error) | 1030 | if (error) |
963 | goto error1; | 1031 | goto out; |
964 | 1032 | ||
965 | xfs_alloc_compute_maxlevels(mp); | 1033 | xfs_alloc_compute_maxlevels(mp); |
966 | xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); | 1034 | xfs_bmap_compute_maxlevels(mp, XFS_DATA_FORK); |
@@ -971,19 +1039,9 @@ xfs_mountfs( | |||
971 | 1039 | ||
972 | mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); | 1040 | mp->m_maxioffset = xfs_max_file_offset(sbp->sb_blocklog); |
973 | 1041 | ||
974 | /* | 1042 | error = xfs_uuid_mount(mp); |
975 | * XFS uses the uuid from the superblock as the unique | 1043 | if (error) |
976 | * identifier for fsid. We can not use the uuid from the volume | 1044 | goto out; |
977 | * since a single partition filesystem is identical to a single | ||
978 | * partition volume/filesystem. | ||
979 | */ | ||
980 | if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) { | ||
981 | if (xfs_uuid_mount(mp)) { | ||
982 | error = XFS_ERROR(EINVAL); | ||
983 | goto error1; | ||
984 | } | ||
985 | uuid_mounted=1; | ||
986 | } | ||
987 | 1045 | ||
988 | /* | 1046 | /* |
989 | * Set the minimum read and write sizes | 1047 | * Set the minimum read and write sizes |
@@ -1007,7 +1065,7 @@ xfs_mountfs( | |||
1007 | */ | 1065 | */ |
1008 | error = xfs_check_sizes(mp); | 1066 | error = xfs_check_sizes(mp); |
1009 | if (error) | 1067 | if (error) |
1010 | goto error1; | 1068 | goto out_remove_uuid; |
1011 | 1069 | ||
1012 | /* | 1070 | /* |
1013 | * Initialize realtime fields in the mount structure | 1071 | * Initialize realtime fields in the mount structure |
@@ -1015,7 +1073,7 @@ xfs_mountfs( | |||
1015 | error = xfs_rtmount_init(mp); | 1073 | error = xfs_rtmount_init(mp); |
1016 | if (error) { | 1074 | if (error) { |
1017 | cmn_err(CE_WARN, "XFS: RT mount failed"); | 1075 | cmn_err(CE_WARN, "XFS: RT mount failed"); |
1018 | goto error1; | 1076 | goto out_remove_uuid; |
1019 | } | 1077 | } |
1020 | 1078 | ||
1021 | /* | 1079 | /* |
@@ -1045,26 +1103,26 @@ xfs_mountfs( | |||
1045 | mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), | 1103 | mp->m_perag = kmem_zalloc(sbp->sb_agcount * sizeof(xfs_perag_t), |
1046 | KM_MAYFAIL); | 1104 | KM_MAYFAIL); |
1047 | if (!mp->m_perag) | 1105 | if (!mp->m_perag) |
1048 | goto error1; | 1106 | goto out_remove_uuid; |
1049 | 1107 | ||
1050 | mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); | 1108 | mp->m_maxagi = xfs_initialize_perag(mp, sbp->sb_agcount); |
1051 | 1109 | ||
1110 | if (!sbp->sb_logblocks) { | ||
1111 | cmn_err(CE_WARN, "XFS: no log defined"); | ||
1112 | XFS_ERROR_REPORT("xfs_mountfs", XFS_ERRLEVEL_LOW, mp); | ||
1113 | error = XFS_ERROR(EFSCORRUPTED); | ||
1114 | goto out_free_perag; | ||
1115 | } | ||
1116 | |||
1052 | /* | 1117 | /* |
1053 | * log's mount-time initialization. Perform 1st part recovery if needed | 1118 | * log's mount-time initialization. Perform 1st part recovery if needed |
1054 | */ | 1119 | */ |
1055 | if (likely(sbp->sb_logblocks > 0)) { /* check for volume case */ | 1120 | error = xfs_log_mount(mp, mp->m_logdev_targp, |
1056 | error = xfs_log_mount(mp, mp->m_logdev_targp, | 1121 | XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), |
1057 | XFS_FSB_TO_DADDR(mp, sbp->sb_logstart), | 1122 | XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); |
1058 | XFS_FSB_TO_BB(mp, sbp->sb_logblocks)); | 1123 | if (error) { |
1059 | if (error) { | 1124 | cmn_err(CE_WARN, "XFS: log mount failed"); |
1060 | cmn_err(CE_WARN, "XFS: log mount failed"); | 1125 | goto out_free_perag; |
1061 | goto error2; | ||
1062 | } | ||
1063 | } else { /* No log has been defined */ | ||
1064 | cmn_err(CE_WARN, "XFS: no log defined"); | ||
1065 | XFS_ERROR_REPORT("xfs_mountfs_int(1)", XFS_ERRLEVEL_LOW, mp); | ||
1066 | error = XFS_ERROR(EFSCORRUPTED); | ||
1067 | goto error2; | ||
1068 | } | 1126 | } |
1069 | 1127 | ||
1070 | /* | 1128 | /* |
@@ -1086,15 +1144,14 @@ xfs_mountfs( | |||
1086 | * If we are currently making the filesystem, the initialisation will | 1144 | * If we are currently making the filesystem, the initialisation will |
1087 | * fail as the perag data is in an undefined state. | 1145 | * fail as the perag data is in an undefined state. |
1088 | */ | 1146 | */ |
1089 | |||
1090 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) && | 1147 | if (xfs_sb_version_haslazysbcount(&mp->m_sb) && |
1091 | !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && | 1148 | !XFS_LAST_UNMOUNT_WAS_CLEAN(mp) && |
1092 | !mp->m_sb.sb_inprogress) { | 1149 | !mp->m_sb.sb_inprogress) { |
1093 | error = xfs_initialize_perag_data(mp, sbp->sb_agcount); | 1150 | error = xfs_initialize_perag_data(mp, sbp->sb_agcount); |
1094 | if (error) { | 1151 | if (error) |
1095 | goto error2; | 1152 | goto out_free_perag; |
1096 | } | ||
1097 | } | 1153 | } |
1154 | |||
1098 | /* | 1155 | /* |
1099 | * Get and sanity-check the root inode. | 1156 | * Get and sanity-check the root inode. |
1100 | * Save the pointer to it in the mount structure. | 1157 | * Save the pointer to it in the mount structure. |
@@ -1102,7 +1159,7 @@ xfs_mountfs( | |||
1102 | error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0); | 1159 | error = xfs_iget(mp, NULL, sbp->sb_rootino, 0, XFS_ILOCK_EXCL, &rip, 0); |
1103 | if (error) { | 1160 | if (error) { |
1104 | cmn_err(CE_WARN, "XFS: failed to read root inode"); | 1161 | cmn_err(CE_WARN, "XFS: failed to read root inode"); |
1105 | goto error3; | 1162 | goto out_log_dealloc; |
1106 | } | 1163 | } |
1107 | 1164 | ||
1108 | ASSERT(rip != NULL); | 1165 | ASSERT(rip != NULL); |
@@ -1116,7 +1173,7 @@ xfs_mountfs( | |||
1116 | XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, | 1173 | XFS_ERROR_REPORT("xfs_mountfs_int(2)", XFS_ERRLEVEL_LOW, |
1117 | mp); | 1174 | mp); |
1118 | error = XFS_ERROR(EFSCORRUPTED); | 1175 | error = XFS_ERROR(EFSCORRUPTED); |
1119 | goto error4; | 1176 | goto out_rele_rip; |
1120 | } | 1177 | } |
1121 | mp->m_rootip = rip; /* save it */ | 1178 | mp->m_rootip = rip; /* save it */ |
1122 | 1179 | ||
@@ -1131,7 +1188,7 @@ xfs_mountfs( | |||
1131 | * Free up the root inode. | 1188 | * Free up the root inode. |
1132 | */ | 1189 | */ |
1133 | cmn_err(CE_WARN, "XFS: failed to read RT inodes"); | 1190 | cmn_err(CE_WARN, "XFS: failed to read RT inodes"); |
1134 | goto error4; | 1191 | goto out_rele_rip; |
1135 | } | 1192 | } |
1136 | 1193 | ||
1137 | /* | 1194 | /* |
@@ -1143,7 +1200,7 @@ xfs_mountfs( | |||
1143 | error = xfs_mount_log_sb(mp, mp->m_update_flags); | 1200 | error = xfs_mount_log_sb(mp, mp->m_update_flags); |
1144 | if (error) { | 1201 | if (error) { |
1145 | cmn_err(CE_WARN, "XFS: failed to write sb changes"); | 1202 | cmn_err(CE_WARN, "XFS: failed to write sb changes"); |
1146 | goto error4; | 1203 | goto out_rtunmount; |
1147 | } | 1204 | } |
1148 | } | 1205 | } |
1149 | 1206 | ||
@@ -1152,7 +1209,7 @@ xfs_mountfs( | |||
1152 | */ | 1209 | */ |
1153 | error = XFS_QM_INIT(mp, "amount, "aflags); | 1210 | error = XFS_QM_INIT(mp, "amount, "aflags); |
1154 | if (error) | 1211 | if (error) |
1155 | goto error4; | 1212 | goto out_rtunmount; |
1156 | 1213 | ||
1157 | /* | 1214 | /* |
1158 | * Finish recovering the file system. This part needed to be | 1215 | * Finish recovering the file system. This part needed to be |
@@ -1162,7 +1219,7 @@ xfs_mountfs( | |||
1162 | error = xfs_log_mount_finish(mp); | 1219 | error = xfs_log_mount_finish(mp); |
1163 | if (error) { | 1220 | if (error) { |
1164 | cmn_err(CE_WARN, "XFS: log mount finish failed"); | 1221 | cmn_err(CE_WARN, "XFS: log mount finish failed"); |
1165 | goto error4; | 1222 | goto out_rtunmount; |
1166 | } | 1223 | } |
1167 | 1224 | ||
1168 | /* | 1225 | /* |
@@ -1170,7 +1227,7 @@ xfs_mountfs( | |||
1170 | */ | 1227 | */ |
1171 | error = XFS_QM_MOUNT(mp, quotamount, quotaflags); | 1228 | error = XFS_QM_MOUNT(mp, quotamount, quotaflags); |
1172 | if (error) | 1229 | if (error) |
1173 | goto error4; | 1230 | goto out_rtunmount; |
1174 | 1231 | ||
1175 | /* | 1232 | /* |
1176 | * Now we are mounted, reserve a small amount of unused space for | 1233 | * Now we are mounted, reserve a small amount of unused space for |
@@ -1194,18 +1251,17 @@ xfs_mountfs( | |||
1194 | 1251 | ||
1195 | return 0; | 1252 | return 0; |
1196 | 1253 | ||
1197 | error4: | 1254 | out_rtunmount: |
1198 | /* | 1255 | xfs_rtunmount_inodes(mp); |
1199 | * Free up the root inode. | 1256 | out_rele_rip: |
1200 | */ | ||
1201 | IRELE(rip); | 1257 | IRELE(rip); |
1202 | error3: | 1258 | out_log_dealloc: |
1203 | xfs_log_unmount_dealloc(mp); | 1259 | xfs_log_unmount(mp); |
1204 | error2: | 1260 | out_free_perag: |
1205 | xfs_free_perag(mp); | 1261 | xfs_free_perag(mp); |
1206 | error1: | 1262 | out_remove_uuid: |
1207 | if (uuid_mounted) | 1263 | xfs_uuid_unmount(mp); |
1208 | uuid_table_remove(&mp->m_sb.sb_uuid); | 1264 | out: |
1209 | return error; | 1265 | return error; |
1210 | } | 1266 | } |
1211 | 1267 | ||
@@ -1226,15 +1282,12 @@ xfs_unmountfs( | |||
1226 | */ | 1282 | */ |
1227 | XFS_QM_UNMOUNT(mp); | 1283 | XFS_QM_UNMOUNT(mp); |
1228 | 1284 | ||
1229 | if (mp->m_rbmip) | 1285 | xfs_rtunmount_inodes(mp); |
1230 | IRELE(mp->m_rbmip); | ||
1231 | if (mp->m_rsumip) | ||
1232 | IRELE(mp->m_rsumip); | ||
1233 | IRELE(mp->m_rootip); | 1286 | IRELE(mp->m_rootip); |
1234 | 1287 | ||
1235 | /* | 1288 | /* |
1236 | * We can potentially deadlock here if we have an inode cluster | 1289 | * We can potentially deadlock here if we have an inode cluster |
1237 | * that has been freed has it's buffer still pinned in memory because | 1290 | * that has been freed has its buffer still pinned in memory because |
1238 | * the transaction is still sitting in a iclog. The stale inodes | 1291 | * the transaction is still sitting in a iclog. The stale inodes |
1239 | * on that buffer will have their flush locks held until the | 1292 | * on that buffer will have their flush locks held until the |
1240 | * transaction hits the disk and the callbacks run. the inode | 1293 | * transaction hits the disk and the callbacks run. the inode |
@@ -1266,7 +1319,7 @@ xfs_unmountfs( | |||
1266 | * Unreserve any blocks we have so that when we unmount we don't account | 1319 | * Unreserve any blocks we have so that when we unmount we don't account |
1267 | * the reserved free space as used. This is really only necessary for | 1320 | * the reserved free space as used. This is really only necessary for |
1268 | * lazy superblock counting because it trusts the incore superblock | 1321 | * lazy superblock counting because it trusts the incore superblock |
1269 | * counters to be aboslutely correct on clean unmount. | 1322 | * counters to be absolutely correct on clean unmount. |
1270 | * | 1323 | * |
1271 | * We don't bother correcting this elsewhere for lazy superblock | 1324 | * We don't bother correcting this elsewhere for lazy superblock |
1272 | * counting because on mount of an unclean filesystem we reconstruct the | 1325 | * counting because on mount of an unclean filesystem we reconstruct the |
@@ -1288,10 +1341,9 @@ xfs_unmountfs( | |||
1288 | "Freespace may not be correct on next mount."); | 1341 | "Freespace may not be correct on next mount."); |
1289 | xfs_unmountfs_writesb(mp); | 1342 | xfs_unmountfs_writesb(mp); |
1290 | xfs_unmountfs_wait(mp); /* wait for async bufs */ | 1343 | xfs_unmountfs_wait(mp); /* wait for async bufs */ |
1291 | xfs_log_unmount(mp); /* Done! No more fs ops. */ | 1344 | xfs_log_unmount_write(mp); |
1292 | 1345 | xfs_log_unmount(mp); | |
1293 | if ((mp->m_flags & XFS_MOUNT_NOUUID) == 0) | 1346 | xfs_uuid_unmount(mp); |
1294 | uuid_table_remove(&mp->m_sb.sb_uuid); | ||
1295 | 1347 | ||
1296 | #if defined(DEBUG) | 1348 | #if defined(DEBUG) |
1297 | xfs_errortag_clearall(mp, 0); | 1349 | xfs_errortag_clearall(mp, 0); |
@@ -1793,29 +1845,6 @@ xfs_freesb( | |||
1793 | } | 1845 | } |
1794 | 1846 | ||
1795 | /* | 1847 | /* |
1796 | * See if the UUID is unique among mounted XFS filesystems. | ||
1797 | * Mount fails if UUID is nil or a FS with the same UUID is already mounted. | ||
1798 | */ | ||
1799 | STATIC int | ||
1800 | xfs_uuid_mount( | ||
1801 | xfs_mount_t *mp) | ||
1802 | { | ||
1803 | if (uuid_is_nil(&mp->m_sb.sb_uuid)) { | ||
1804 | cmn_err(CE_WARN, | ||
1805 | "XFS: Filesystem %s has nil UUID - can't mount", | ||
1806 | mp->m_fsname); | ||
1807 | return -1; | ||
1808 | } | ||
1809 | if (!uuid_table_insert(&mp->m_sb.sb_uuid)) { | ||
1810 | cmn_err(CE_WARN, | ||
1811 | "XFS: Filesystem %s has duplicate UUID - can't mount", | ||
1812 | mp->m_fsname); | ||
1813 | return -1; | ||
1814 | } | ||
1815 | return 0; | ||
1816 | } | ||
1817 | |||
1818 | /* | ||
1819 | * Used to log changes to the superblock unit and width fields which could | 1848 | * Used to log changes to the superblock unit and width fields which could |
1820 | * be altered by the mount options, as well as any potential sb_features2 | 1849 | * be altered by the mount options, as well as any potential sb_features2 |
1821 | * fixup. Only the first superblock is updated. | 1850 | * fixup. Only the first superblock is updated. |
@@ -1868,7 +1897,7 @@ xfs_mount_log_sb( | |||
1868 | * we disable the per-cpu counter and go through the slow path. | 1897 | * we disable the per-cpu counter and go through the slow path. |
1869 | * | 1898 | * |
1870 | * The slow path is the current xfs_mod_incore_sb() function. This means that | 1899 | * The slow path is the current xfs_mod_incore_sb() function. This means that |
1871 | * when we disable a per-cpu counter, we need to drain it's resources back to | 1900 | * when we disable a per-cpu counter, we need to drain its resources back to |
1872 | * the global superblock. We do this after disabling the counter to prevent | 1901 | * the global superblock. We do this after disabling the counter to prevent |
1873 | * more threads from queueing up on the counter. | 1902 | * more threads from queueing up on the counter. |
1874 | * | 1903 | * |
diff --git a/fs/xfs/xfs_mount.h b/fs/xfs/xfs_mount.h index f5e9937f9bdb..7af44adffc8f 100644 --- a/fs/xfs/xfs_mount.h +++ b/fs/xfs/xfs_mount.h | |||
@@ -136,7 +136,6 @@ typedef int (*xfs_dqvopchownresv_t)(struct xfs_trans *, struct xfs_inode *, | |||
136 | struct xfs_dquot *, struct xfs_dquot *, uint); | 136 | struct xfs_dquot *, struct xfs_dquot *, uint); |
137 | typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, struct kstatfs *); | 137 | typedef void (*xfs_dqstatvfs_t)(struct xfs_inode *, struct kstatfs *); |
138 | typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags); | 138 | typedef int (*xfs_dqsync_t)(struct xfs_mount *, int flags); |
139 | typedef int (*xfs_quotactl_t)(struct xfs_mount *, int, int, xfs_caddr_t); | ||
140 | 139 | ||
141 | typedef struct xfs_qmops { | 140 | typedef struct xfs_qmops { |
142 | xfs_qminit_t xfs_qminit; | 141 | xfs_qminit_t xfs_qminit; |
@@ -154,7 +153,6 @@ typedef struct xfs_qmops { | |||
154 | xfs_dqvopchownresv_t xfs_dqvopchownresv; | 153 | xfs_dqvopchownresv_t xfs_dqvopchownresv; |
155 | xfs_dqstatvfs_t xfs_dqstatvfs; | 154 | xfs_dqstatvfs_t xfs_dqstatvfs; |
156 | xfs_dqsync_t xfs_dqsync; | 155 | xfs_dqsync_t xfs_dqsync; |
157 | xfs_quotactl_t xfs_quotactl; | ||
158 | struct xfs_dqtrxops *xfs_dqtrxops; | 156 | struct xfs_dqtrxops *xfs_dqtrxops; |
159 | } xfs_qmops_t; | 157 | } xfs_qmops_t; |
160 | 158 | ||
@@ -188,8 +186,6 @@ typedef struct xfs_qmops { | |||
188 | (*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp) | 186 | (*(ip)->i_mount->m_qm_ops->xfs_dqstatvfs)(ip, statp) |
189 | #define XFS_QM_DQSYNC(mp, flags) \ | 187 | #define XFS_QM_DQSYNC(mp, flags) \ |
190 | (*(mp)->m_qm_ops->xfs_dqsync)(mp, flags) | 188 | (*(mp)->m_qm_ops->xfs_dqsync)(mp, flags) |
191 | #define XFS_QM_QUOTACTL(mp, cmd, id, addr) \ | ||
192 | (*(mp)->m_qm_ops->xfs_quotactl)(mp, cmd, id, addr) | ||
193 | 189 | ||
194 | #ifdef HAVE_PERCPU_SB | 190 | #ifdef HAVE_PERCPU_SB |
195 | 191 | ||
@@ -273,19 +269,17 @@ typedef struct xfs_mount { | |||
273 | uint m_inobt_mnr[2]; /* min inobt btree records */ | 269 | uint m_inobt_mnr[2]; /* min inobt btree records */ |
274 | uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ | 270 | uint m_ag_maxlevels; /* XFS_AG_MAXLEVELS */ |
275 | uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ | 271 | uint m_bm_maxlevels[2]; /* XFS_BM_MAXLEVELS */ |
276 | uint m_in_maxlevels; /* XFS_IN_MAXLEVELS */ | 272 | uint m_in_maxlevels; /* max inobt btree levels. */ |
277 | struct xfs_perag *m_perag; /* per-ag accounting info */ | 273 | struct xfs_perag *m_perag; /* per-ag accounting info */ |
278 | struct rw_semaphore m_peraglock; /* lock for m_perag (pointer) */ | 274 | struct rw_semaphore m_peraglock; /* lock for m_perag (pointer) */ |
279 | struct mutex m_growlock; /* growfs mutex */ | 275 | struct mutex m_growlock; /* growfs mutex */ |
280 | int m_fixedfsid[2]; /* unchanged for life of FS */ | 276 | int m_fixedfsid[2]; /* unchanged for life of FS */ |
281 | uint m_dmevmask; /* DMI events for this FS */ | 277 | uint m_dmevmask; /* DMI events for this FS */ |
282 | __uint64_t m_flags; /* global mount flags */ | 278 | __uint64_t m_flags; /* global mount flags */ |
283 | uint m_attroffset; /* inode attribute offset */ | ||
284 | uint m_dir_node_ents; /* #entries in a dir danode */ | 279 | uint m_dir_node_ents; /* #entries in a dir danode */ |
285 | uint m_attr_node_ents; /* #entries in attr danode */ | 280 | uint m_attr_node_ents; /* #entries in attr danode */ |
286 | int m_ialloc_inos; /* inodes in inode allocation */ | 281 | int m_ialloc_inos; /* inodes in inode allocation */ |
287 | int m_ialloc_blks; /* blocks in inode allocation */ | 282 | int m_ialloc_blks; /* blocks in inode allocation */ |
288 | int m_litino; /* size of inode union area */ | ||
289 | int m_inoalign_mask;/* mask sb_inoalignmt if used */ | 283 | int m_inoalign_mask;/* mask sb_inoalignmt if used */ |
290 | uint m_qflags; /* quota status flags */ | 284 | uint m_qflags; /* quota status flags */ |
291 | xfs_trans_reservations_t m_reservations;/* precomputed res values */ | 285 | xfs_trans_reservations_t m_reservations;/* precomputed res values */ |
@@ -293,9 +287,6 @@ typedef struct xfs_mount { | |||
293 | __uint64_t m_maxioffset; /* maximum inode offset */ | 287 | __uint64_t m_maxioffset; /* maximum inode offset */ |
294 | __uint64_t m_resblks; /* total reserved blocks */ | 288 | __uint64_t m_resblks; /* total reserved blocks */ |
295 | __uint64_t m_resblks_avail;/* available reserved blocks */ | 289 | __uint64_t m_resblks_avail;/* available reserved blocks */ |
296 | #if XFS_BIG_INUMS | ||
297 | xfs_ino_t m_inoadd; /* add value for ino64_offset */ | ||
298 | #endif | ||
299 | int m_dalign; /* stripe unit */ | 290 | int m_dalign; /* stripe unit */ |
300 | int m_swidth; /* stripe width */ | 291 | int m_swidth; /* stripe width */ |
301 | int m_sinoalign; /* stripe unit inode alignment */ | 292 | int m_sinoalign; /* stripe unit inode alignment */ |
@@ -337,7 +328,6 @@ typedef struct xfs_mount { | |||
337 | #define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops | 328 | #define XFS_MOUNT_WSYNC (1ULL << 0) /* for nfs - all metadata ops |
338 | must be synchronous except | 329 | must be synchronous except |
339 | for space allocations */ | 330 | for space allocations */ |
340 | #define XFS_MOUNT_INO64 (1ULL << 1) | ||
341 | #define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */ | 331 | #define XFS_MOUNT_DMAPI (1ULL << 2) /* dmapi is enabled */ |
342 | #define XFS_MOUNT_WAS_CLEAN (1ULL << 3) | 332 | #define XFS_MOUNT_WAS_CLEAN (1ULL << 3) |
343 | #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem | 333 | #define XFS_MOUNT_FS_SHUTDOWN (1ULL << 4) /* atomic stop of all filesystem |
@@ -389,8 +379,8 @@ typedef struct xfs_mount { | |||
389 | * Synchronous read and write sizes. This should be | 379 | * Synchronous read and write sizes. This should be |
390 | * better for NFSv2 wsync filesystems. | 380 | * better for NFSv2 wsync filesystems. |
391 | */ | 381 | */ |
392 | #define XFS_WSYNC_READIO_LOG 15 /* 32K */ | 382 | #define XFS_WSYNC_READIO_LOG 15 /* 32k */ |
393 | #define XFS_WSYNC_WRITEIO_LOG 14 /* 16K */ | 383 | #define XFS_WSYNC_WRITEIO_LOG 14 /* 16k */ |
394 | 384 | ||
395 | /* | 385 | /* |
396 | * Allow large block sizes to be reported to userspace programs if the | 386 | * Allow large block sizes to be reported to userspace programs if the |
@@ -500,9 +490,6 @@ typedef struct xfs_mod_sb { | |||
500 | int64_t msb_delta; /* Change to make to specified field */ | 490 | int64_t msb_delta; /* Change to make to specified field */ |
501 | } xfs_mod_sb_t; | 491 | } xfs_mod_sb_t; |
502 | 492 | ||
503 | #define XFS_MOUNT_ILOCK(mp) mutex_lock(&((mp)->m_ilock)) | ||
504 | #define XFS_MOUNT_IUNLOCK(mp) mutex_unlock(&((mp)->m_ilock)) | ||
505 | |||
506 | extern int xfs_log_sbcount(xfs_mount_t *, uint); | 493 | extern int xfs_log_sbcount(xfs_mount_t *, uint); |
507 | extern int xfs_mountfs(xfs_mount_t *mp); | 494 | extern int xfs_mountfs(xfs_mount_t *mp); |
508 | extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); | 495 | extern void xfs_mountfs_check_barriers(xfs_mount_t *mp); |
diff --git a/fs/xfs/xfs_qmops.c b/fs/xfs/xfs_qmops.c index 27f80581520a..e101790ea8e7 100644 --- a/fs/xfs/xfs_qmops.c +++ b/fs/xfs/xfs_qmops.c | |||
@@ -126,7 +126,6 @@ static struct xfs_qmops xfs_qmcore_stub = { | |||
126 | .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr, | 126 | .xfs_dqvopchownresv = (xfs_dqvopchownresv_t) fs_noerr, |
127 | .xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval, | 127 | .xfs_dqstatvfs = (xfs_dqstatvfs_t) fs_noval, |
128 | .xfs_dqsync = (xfs_dqsync_t) fs_noerr, | 128 | .xfs_dqsync = (xfs_dqsync_t) fs_noerr, |
129 | .xfs_quotactl = (xfs_quotactl_t) fs_nosys, | ||
130 | }; | 129 | }; |
131 | 130 | ||
132 | int | 131 | int |
diff --git a/fs/xfs/xfs_quota.h b/fs/xfs/xfs_quota.h index 48965ecaa155..f5d1202dde25 100644 --- a/fs/xfs/xfs_quota.h +++ b/fs/xfs/xfs_quota.h | |||
@@ -18,6 +18,8 @@ | |||
18 | #ifndef __XFS_QUOTA_H__ | 18 | #ifndef __XFS_QUOTA_H__ |
19 | #define __XFS_QUOTA_H__ | 19 | #define __XFS_QUOTA_H__ |
20 | 20 | ||
21 | struct xfs_trans; | ||
22 | |||
21 | /* | 23 | /* |
22 | * The ondisk form of a dquot structure. | 24 | * The ondisk form of a dquot structure. |
23 | */ | 25 | */ |
@@ -185,7 +187,6 @@ typedef struct xfs_qoff_logformat { | |||
185 | * to a single function. None of these XFS_QMOPT_* flags are meant to have | 187 | * to a single function. None of these XFS_QMOPT_* flags are meant to have |
186 | * persistent values (ie. their values can and will change between versions) | 188 | * persistent values (ie. their values can and will change between versions) |
187 | */ | 189 | */ |
188 | #define XFS_QMOPT_DQLOCK 0x0000001 /* dqlock */ | ||
189 | #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ | 190 | #define XFS_QMOPT_DQALLOC 0x0000002 /* alloc dquot ondisk if needed */ |
190 | #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ | 191 | #define XFS_QMOPT_UQUOTA 0x0000004 /* user dquot requested */ |
191 | #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ | 192 | #define XFS_QMOPT_PQUOTA 0x0000008 /* project dquot requested */ |
diff --git a/fs/xfs/xfs_rtalloc.c b/fs/xfs/xfs_rtalloc.c index c5bb86f3ec05..385f6dceba5d 100644 --- a/fs/xfs/xfs_rtalloc.c +++ b/fs/xfs/xfs_rtalloc.c | |||
@@ -2288,6 +2288,16 @@ xfs_rtmount_inodes( | |||
2288 | return 0; | 2288 | return 0; |
2289 | } | 2289 | } |
2290 | 2290 | ||
2291 | void | ||
2292 | xfs_rtunmount_inodes( | ||
2293 | struct xfs_mount *mp) | ||
2294 | { | ||
2295 | if (mp->m_rbmip) | ||
2296 | IRELE(mp->m_rbmip); | ||
2297 | if (mp->m_rsumip) | ||
2298 | IRELE(mp->m_rsumip); | ||
2299 | } | ||
2300 | |||
2291 | /* | 2301 | /* |
2292 | * Pick an extent for allocation at the start of a new realtime file. | 2302 | * Pick an extent for allocation at the start of a new realtime file. |
2293 | * Use the sequence number stored in the atime field of the bitmap inode. | 2303 | * Use the sequence number stored in the atime field of the bitmap inode. |
diff --git a/fs/xfs/xfs_rtalloc.h b/fs/xfs/xfs_rtalloc.h index 8d8dcd215716..b2d67adb6a08 100644 --- a/fs/xfs/xfs_rtalloc.h +++ b/fs/xfs/xfs_rtalloc.h | |||
@@ -23,8 +23,8 @@ struct xfs_trans; | |||
23 | 23 | ||
24 | /* Min and max rt extent sizes, specified in bytes */ | 24 | /* Min and max rt extent sizes, specified in bytes */ |
25 | #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ | 25 | #define XFS_MAX_RTEXTSIZE (1024 * 1024 * 1024) /* 1GB */ |
26 | #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64KB */ | 26 | #define XFS_DFL_RTEXTSIZE (64 * 1024) /* 64kB */ |
27 | #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4KB */ | 27 | #define XFS_MIN_RTEXTSIZE (4 * 1024) /* 4kB */ |
28 | 28 | ||
29 | /* | 29 | /* |
30 | * Constants for bit manipulations. | 30 | * Constants for bit manipulations. |
@@ -108,6 +108,9 @@ xfs_rtfree_extent( | |||
108 | int /* error */ | 108 | int /* error */ |
109 | xfs_rtmount_init( | 109 | xfs_rtmount_init( |
110 | struct xfs_mount *mp); /* file system mount structure */ | 110 | struct xfs_mount *mp); /* file system mount structure */ |
111 | void | ||
112 | xfs_rtunmount_inodes( | ||
113 | struct xfs_mount *mp); | ||
111 | 114 | ||
112 | /* | 115 | /* |
113 | * Get the bitmap and summary inodes into the mount structure | 116 | * Get the bitmap and summary inodes into the mount structure |
@@ -146,6 +149,7 @@ xfs_growfs_rt( | |||
146 | # define xfs_growfs_rt(mp,in) (ENOSYS) | 149 | # define xfs_growfs_rt(mp,in) (ENOSYS) |
147 | # define xfs_rtmount_init(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) | 150 | # define xfs_rtmount_init(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) |
148 | # define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) | 151 | # define xfs_rtmount_inodes(m) (((mp)->m_sb.sb_rblocks == 0)? 0 : (ENOSYS)) |
152 | # define xfs_rtunmount_inodes(m) | ||
149 | #endif /* CONFIG_XFS_RT */ | 153 | #endif /* CONFIG_XFS_RT */ |
150 | 154 | ||
151 | #endif /* __KERNEL__ */ | 155 | #endif /* __KERNEL__ */ |
diff --git a/fs/xfs/xfs_trans.h b/fs/xfs/xfs_trans.h index d6fe4a88d79f..775249a54f6f 100644 --- a/fs/xfs/xfs_trans.h +++ b/fs/xfs/xfs_trans.h | |||
@@ -292,7 +292,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
292 | * In a write transaction we can allocate a maximum of 2 | 292 | * In a write transaction we can allocate a maximum of 2 |
293 | * extents. This gives: | 293 | * extents. This gives: |
294 | * the inode getting the new extents: inode size | 294 | * the inode getting the new extents: inode size |
295 | * the inode\'s bmap btree: max depth * block size | 295 | * the inode's bmap btree: max depth * block size |
296 | * the agfs of the ags from which the extents are allocated: 2 * sector | 296 | * the agfs of the ags from which the extents are allocated: 2 * sector |
297 | * the superblock free block counter: sector size | 297 | * the superblock free block counter: sector size |
298 | * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size | 298 | * the allocation btrees: 2 exts * 2 trees * (2 * max depth - 1) * block size |
@@ -321,7 +321,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
321 | /* | 321 | /* |
322 | * In truncating a file we free up to two extents at once. We can modify: | 322 | * In truncating a file we free up to two extents at once. We can modify: |
323 | * the inode being truncated: inode size | 323 | * the inode being truncated: inode size |
324 | * the inode\'s bmap btree: (max depth + 1) * block size | 324 | * the inode's bmap btree: (max depth + 1) * block size |
325 | * And the bmap_finish transaction can free the blocks and bmap blocks: | 325 | * And the bmap_finish transaction can free the blocks and bmap blocks: |
326 | * the agf for each of the ags: 4 * sector size | 326 | * the agf for each of the ags: 4 * sector size |
327 | * the agfl for each of the ags: 4 * sector size | 327 | * the agfl for each of the ags: 4 * sector size |
@@ -343,7 +343,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
343 | (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \ | 343 | (128 * (9 + XFS_ALLOCFREE_LOG_COUNT(mp, 4))) + \ |
344 | (128 * 5) + \ | 344 | (128 * 5) + \ |
345 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ | 345 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ |
346 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ | 346 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \ |
347 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) | 347 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) |
348 | 348 | ||
349 | #define XFS_ITRUNCATE_LOG_RES(mp) ((mp)->m_reservations.tr_itruncate) | 349 | #define XFS_ITRUNCATE_LOG_RES(mp) ((mp)->m_reservations.tr_itruncate) |
@@ -431,8 +431,8 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
431 | * the new inode: inode size | 431 | * the new inode: inode size |
432 | * the inode btree entry: 1 block | 432 | * the inode btree entry: 1 block |
433 | * the directory btree: (max depth + v2) * dir block size | 433 | * the directory btree: (max depth + v2) * dir block size |
434 | * the directory inode\'s bmap btree: (max depth + v2) * block size | 434 | * the directory inode's bmap btree: (max depth + v2) * block size |
435 | * the blocks for the symlink: 1 KB | 435 | * the blocks for the symlink: 1 kB |
436 | * Or in the first xact we allocate some inodes giving: | 436 | * Or in the first xact we allocate some inodes giving: |
437 | * the agi and agf of the ag getting the new inodes: 2 * sectorsize | 437 | * the agi and agf of the ag getting the new inodes: 2 * sectorsize |
438 | * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize | 438 | * the inode blocks allocated: XFS_IALLOC_BLOCKS * blocksize |
@@ -449,9 +449,9 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
449 | (128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \ | 449 | (128 * (4 + XFS_DIROP_LOG_COUNT(mp)))), \ |
450 | (2 * (mp)->m_sb.sb_sectsize + \ | 450 | (2 * (mp)->m_sb.sb_sectsize + \ |
451 | XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \ | 451 | XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \ |
452 | XFS_FSB_TO_B((mp), XFS_IN_MAXLEVELS(mp)) + \ | 452 | XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \ |
453 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ | 453 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ |
454 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ | 454 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \ |
455 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) | 455 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) |
456 | 456 | ||
457 | #define XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink) | 457 | #define XFS_SYMLINK_LOG_RES(mp) ((mp)->m_reservations.tr_symlink) |
@@ -463,7 +463,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
463 | * the inode btree entry: block size | 463 | * the inode btree entry: block size |
464 | * the superblock for the nlink flag: sector size | 464 | * the superblock for the nlink flag: sector size |
465 | * the directory btree: (max depth + v2) * dir block size | 465 | * the directory btree: (max depth + v2) * dir block size |
466 | * the directory inode\'s bmap btree: (max depth + v2) * block size | 466 | * the directory inode's bmap btree: (max depth + v2) * block size |
467 | * Or in the first xact we allocate some inodes giving: | 467 | * Or in the first xact we allocate some inodes giving: |
468 | * the agi and agf of the ag getting the new inodes: 2 * sectorsize | 468 | * the agi and agf of the ag getting the new inodes: 2 * sectorsize |
469 | * the superblock for the nlink flag: sector size | 469 | * the superblock for the nlink flag: sector size |
@@ -481,9 +481,9 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
481 | (128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \ | 481 | (128 * (3 + XFS_DIROP_LOG_COUNT(mp)))), \ |
482 | (3 * (mp)->m_sb.sb_sectsize + \ | 482 | (3 * (mp)->m_sb.sb_sectsize + \ |
483 | XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \ | 483 | XFS_FSB_TO_B((mp), XFS_IALLOC_BLOCKS((mp))) + \ |
484 | XFS_FSB_TO_B((mp), XFS_IN_MAXLEVELS(mp)) + \ | 484 | XFS_FSB_TO_B((mp), (mp)->m_in_maxlevels) + \ |
485 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ | 485 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ |
486 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ | 486 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \ |
487 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) | 487 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))))) |
488 | 488 | ||
489 | #define XFS_CREATE_LOG_RES(mp) ((mp)->m_reservations.tr_create) | 489 | #define XFS_CREATE_LOG_RES(mp) ((mp)->m_reservations.tr_create) |
@@ -513,7 +513,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
513 | MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \ | 513 | MAX((__uint16_t)XFS_FSB_TO_B((mp), 1), XFS_INODE_CLUSTER_SIZE(mp)) + \ |
514 | (128 * 5) + \ | 514 | (128 * 5) + \ |
515 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ | 515 | XFS_ALLOCFREE_LOG_RES(mp, 1) + \ |
516 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp) + \ | 516 | (128 * (2 + XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels + \ |
517 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) | 517 | XFS_ALLOCFREE_LOG_COUNT(mp, 1)))) |
518 | 518 | ||
519 | 519 | ||
@@ -637,7 +637,7 @@ xfs_lic_desc_to_chunk(xfs_log_item_desc_t *dp) | |||
637 | /* | 637 | /* |
638 | * Removing the attribute fork of a file | 638 | * Removing the attribute fork of a file |
639 | * the inode being truncated: inode size | 639 | * the inode being truncated: inode size |
640 | * the inode\'s bmap btree: max depth * block size | 640 | * the inode's bmap btree: max depth * block size |
641 | * And the bmap_finish transaction can free the blocks and bmap blocks: | 641 | * And the bmap_finish transaction can free the blocks and bmap blocks: |
642 | * the agf for each of the ags: 4 * sector size | 642 | * the agf for each of the ags: 4 * sector size |
643 | * the agfl for each of the ags: 4 * sector size | 643 | * the agfl for each of the ags: 4 * sector size |
diff --git a/fs/xfs/xfs_trans_ail.c b/fs/xfs/xfs_trans_ail.c index 2d47f10f8bed..f31271c30de9 100644 --- a/fs/xfs/xfs_trans_ail.c +++ b/fs/xfs/xfs_trans_ail.c | |||
@@ -79,7 +79,7 @@ xfs_trans_ail_tail( | |||
79 | * the push is run asynchronously in a separate thread, so we return the tail | 79 | * the push is run asynchronously in a separate thread, so we return the tail |
80 | * of the log right now instead of the tail after the push. This means we will | 80 | * of the log right now instead of the tail after the push. This means we will |
81 | * either continue right away, or we will sleep waiting on the async thread to | 81 | * either continue right away, or we will sleep waiting on the async thread to |
82 | * do it's work. | 82 | * do its work. |
83 | * | 83 | * |
84 | * We do this unlocked - we only need to know whether there is anything in the | 84 | * We do this unlocked - we only need to know whether there is anything in the |
85 | * AIL at the time we are called. We don't need to access the contents of | 85 | * AIL at the time we are called. We don't need to access the contents of |
@@ -160,7 +160,7 @@ xfs_trans_ail_cursor_next( | |||
160 | /* | 160 | /* |
161 | * Now that the traversal is complete, we need to remove the cursor | 161 | * Now that the traversal is complete, we need to remove the cursor |
162 | * from the list of traversing cursors. Avoid removing the embedded | 162 | * from the list of traversing cursors. Avoid removing the embedded |
163 | * push cursor, but use the fact it is alway present to make the | 163 | * push cursor, but use the fact it is always present to make the |
164 | * list deletion simple. | 164 | * list deletion simple. |
165 | */ | 165 | */ |
166 | void | 166 | void |
diff --git a/fs/xfs/xfs_trans_item.c b/fs/xfs/xfs_trans_item.c index e110bf57d7f4..eb3fc57f9eef 100644 --- a/fs/xfs/xfs_trans_item.c +++ b/fs/xfs/xfs_trans_item.c | |||
@@ -22,7 +22,7 @@ | |||
22 | #include "xfs_inum.h" | 22 | #include "xfs_inum.h" |
23 | #include "xfs_trans.h" | 23 | #include "xfs_trans.h" |
24 | #include "xfs_trans_priv.h" | 24 | #include "xfs_trans_priv.h" |
25 | /* XXX: from here down needed until struct xfs_trans has it's own ailp */ | 25 | /* XXX: from here down needed until struct xfs_trans has its own ailp */ |
26 | #include "xfs_bit.h" | 26 | #include "xfs_bit.h" |
27 | #include "xfs_buf_item.h" | 27 | #include "xfs_buf_item.h" |
28 | #include "xfs_sb.h" | 28 | #include "xfs_sb.h" |
diff --git a/fs/xfs/xfs_trans_space.h b/fs/xfs/xfs_trans_space.h index 4ea2e5074bdd..7d2c920dfb9c 100644 --- a/fs/xfs/xfs_trans_space.h +++ b/fs/xfs/xfs_trans_space.h | |||
@@ -47,7 +47,7 @@ | |||
47 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ | 47 | #define XFS_DIRREMOVE_SPACE_RES(mp) \ |
48 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) | 48 | XFS_DAREMOVE_SPACE_RES(mp, XFS_DATA_FORK) |
49 | #define XFS_IALLOC_SPACE_RES(mp) \ | 49 | #define XFS_IALLOC_SPACE_RES(mp) \ |
50 | (XFS_IALLOC_BLOCKS(mp) + XFS_IN_MAXLEVELS(mp)-1) | 50 | (XFS_IALLOC_BLOCKS(mp) + (mp)->m_in_maxlevels - 1) |
51 | 51 | ||
52 | /* | 52 | /* |
53 | * Space reservation values for various transactions. | 53 | * Space reservation values for various transactions. |
diff --git a/fs/xfs/xfs_types.h b/fs/xfs/xfs_types.h index b2f724502f1b..d725428c9df6 100644 --- a/fs/xfs/xfs_types.h +++ b/fs/xfs/xfs_types.h | |||
@@ -21,14 +21,6 @@ | |||
21 | #ifdef __KERNEL__ | 21 | #ifdef __KERNEL__ |
22 | 22 | ||
23 | /* | 23 | /* |
24 | * POSIX Extensions | ||
25 | */ | ||
26 | typedef unsigned char uchar_t; | ||
27 | typedef unsigned short ushort_t; | ||
28 | typedef unsigned int uint_t; | ||
29 | typedef unsigned long ulong_t; | ||
30 | |||
31 | /* | ||
32 | * Additional type declarations for XFS | 24 | * Additional type declarations for XFS |
33 | */ | 25 | */ |
34 | typedef signed char __int8_t; | 26 | typedef signed char __int8_t; |
diff --git a/fs/xfs/xfs_utils.c b/fs/xfs/xfs_utils.c index fcc2285d03ed..79b9e5ea5359 100644 --- a/fs/xfs/xfs_utils.c +++ b/fs/xfs/xfs_utils.c | |||
@@ -374,7 +374,7 @@ xfs_truncate_file( | |||
374 | 374 | ||
375 | /* | 375 | /* |
376 | * Follow the normal truncate locking protocol. Since we | 376 | * Follow the normal truncate locking protocol. Since we |
377 | * hold the inode in the transaction, we know that it's number | 377 | * hold the inode in the transaction, we know that its number |
378 | * of references will stay constant. | 378 | * of references will stay constant. |
379 | */ | 379 | */ |
380 | xfs_ilock(ip, XFS_ILOCK_EXCL); | 380 | xfs_ilock(ip, XFS_ILOCK_EXCL); |
diff --git a/fs/xfs/xfs_vnodeops.c b/fs/xfs/xfs_vnodeops.c index 0e55c5d7db5f..7394c7af5de5 100644 --- a/fs/xfs/xfs_vnodeops.c +++ b/fs/xfs/xfs_vnodeops.c | |||
@@ -1136,7 +1136,7 @@ xfs_inactive( | |||
1136 | * If the inode is already free, then there can be nothing | 1136 | * If the inode is already free, then there can be nothing |
1137 | * to clean up here. | 1137 | * to clean up here. |
1138 | */ | 1138 | */ |
1139 | if (ip->i_d.di_mode == 0 || VN_BAD(VFS_I(ip))) { | 1139 | if (ip->i_d.di_mode == 0 || is_bad_inode(VFS_I(ip))) { |
1140 | ASSERT(ip->i_df.if_real_bytes == 0); | 1140 | ASSERT(ip->i_df.if_real_bytes == 0); |
1141 | ASSERT(ip->i_df.if_broot_bytes == 0); | 1141 | ASSERT(ip->i_df.if_broot_bytes == 0); |
1142 | return VN_INACTIVE_CACHE; | 1142 | return VN_INACTIVE_CACHE; |
@@ -1387,23 +1387,28 @@ xfs_create( | |||
1387 | xfs_inode_t **ipp, | 1387 | xfs_inode_t **ipp, |
1388 | cred_t *credp) | 1388 | cred_t *credp) |
1389 | { | 1389 | { |
1390 | xfs_mount_t *mp = dp->i_mount; | 1390 | int is_dir = S_ISDIR(mode); |
1391 | xfs_inode_t *ip; | 1391 | struct xfs_mount *mp = dp->i_mount; |
1392 | xfs_trans_t *tp; | 1392 | struct xfs_inode *ip = NULL; |
1393 | struct xfs_trans *tp = NULL; | ||
1393 | int error; | 1394 | int error; |
1394 | xfs_bmap_free_t free_list; | 1395 | xfs_bmap_free_t free_list; |
1395 | xfs_fsblock_t first_block; | 1396 | xfs_fsblock_t first_block; |
1396 | boolean_t unlock_dp_on_error = B_FALSE; | 1397 | boolean_t unlock_dp_on_error = B_FALSE; |
1397 | int dm_event_sent = 0; | ||
1398 | uint cancel_flags; | 1398 | uint cancel_flags; |
1399 | int committed; | 1399 | int committed; |
1400 | xfs_prid_t prid; | 1400 | xfs_prid_t prid; |
1401 | struct xfs_dquot *udqp, *gdqp; | 1401 | struct xfs_dquot *udqp = NULL; |
1402 | struct xfs_dquot *gdqp = NULL; | ||
1402 | uint resblks; | 1403 | uint resblks; |
1404 | uint log_res; | ||
1405 | uint log_count; | ||
1403 | 1406 | ||
1404 | ASSERT(!*ipp); | ||
1405 | xfs_itrace_entry(dp); | 1407 | xfs_itrace_entry(dp); |
1406 | 1408 | ||
1409 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
1410 | return XFS_ERROR(EIO); | ||
1411 | |||
1407 | if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { | 1412 | if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { |
1408 | error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, | 1413 | error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, |
1409 | dp, DM_RIGHT_NULL, NULL, | 1414 | dp, DM_RIGHT_NULL, NULL, |
@@ -1412,84 +1417,97 @@ xfs_create( | |||
1412 | 1417 | ||
1413 | if (error) | 1418 | if (error) |
1414 | return error; | 1419 | return error; |
1415 | dm_event_sent = 1; | ||
1416 | } | 1420 | } |
1417 | 1421 | ||
1418 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
1419 | return XFS_ERROR(EIO); | ||
1420 | |||
1421 | /* Return through std_return after this point. */ | ||
1422 | |||
1423 | udqp = gdqp = NULL; | ||
1424 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | 1422 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) |
1425 | prid = dp->i_d.di_projid; | 1423 | prid = dp->i_d.di_projid; |
1426 | else | 1424 | else |
1427 | prid = (xfs_prid_t)dfltprid; | 1425 | prid = dfltprid; |
1428 | 1426 | ||
1429 | /* | 1427 | /* |
1430 | * Make sure that we have allocated dquot(s) on disk. | 1428 | * Make sure that we have allocated dquot(s) on disk. |
1431 | */ | 1429 | */ |
1432 | error = XFS_QM_DQVOPALLOC(mp, dp, | 1430 | error = XFS_QM_DQVOPALLOC(mp, dp, |
1433 | current_fsuid(), current_fsgid(), prid, | 1431 | current_fsuid(), current_fsgid(), prid, |
1434 | XFS_QMOPT_QUOTALL|XFS_QMOPT_INHERIT, &udqp, &gdqp); | 1432 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); |
1435 | if (error) | 1433 | if (error) |
1436 | goto std_return; | 1434 | goto std_return; |
1437 | 1435 | ||
1438 | ip = NULL; | 1436 | if (is_dir) { |
1437 | rdev = 0; | ||
1438 | resblks = XFS_MKDIR_SPACE_RES(mp, name->len); | ||
1439 | log_res = XFS_MKDIR_LOG_RES(mp); | ||
1440 | log_count = XFS_MKDIR_LOG_COUNT; | ||
1441 | tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR); | ||
1442 | } else { | ||
1443 | resblks = XFS_CREATE_SPACE_RES(mp, name->len); | ||
1444 | log_res = XFS_CREATE_LOG_RES(mp); | ||
1445 | log_count = XFS_CREATE_LOG_COUNT; | ||
1446 | tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE); | ||
1447 | } | ||
1439 | 1448 | ||
1440 | tp = xfs_trans_alloc(mp, XFS_TRANS_CREATE); | ||
1441 | cancel_flags = XFS_TRANS_RELEASE_LOG_RES; | 1449 | cancel_flags = XFS_TRANS_RELEASE_LOG_RES; |
1442 | resblks = XFS_CREATE_SPACE_RES(mp, name->len); | 1450 | |
1443 | /* | 1451 | /* |
1444 | * Initially assume that the file does not exist and | 1452 | * Initially assume that the file does not exist and |
1445 | * reserve the resources for that case. If that is not | 1453 | * reserve the resources for that case. If that is not |
1446 | * the case we'll drop the one we have and get a more | 1454 | * the case we'll drop the one we have and get a more |
1447 | * appropriate transaction later. | 1455 | * appropriate transaction later. |
1448 | */ | 1456 | */ |
1449 | error = xfs_trans_reserve(tp, resblks, XFS_CREATE_LOG_RES(mp), 0, | 1457 | error = xfs_trans_reserve(tp, resblks, log_res, 0, |
1450 | XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); | 1458 | XFS_TRANS_PERM_LOG_RES, log_count); |
1451 | if (error == ENOSPC) { | 1459 | if (error == ENOSPC) { |
1452 | resblks = 0; | 1460 | resblks = 0; |
1453 | error = xfs_trans_reserve(tp, 0, XFS_CREATE_LOG_RES(mp), 0, | 1461 | error = xfs_trans_reserve(tp, 0, log_res, 0, |
1454 | XFS_TRANS_PERM_LOG_RES, XFS_CREATE_LOG_COUNT); | 1462 | XFS_TRANS_PERM_LOG_RES, log_count); |
1455 | } | 1463 | } |
1456 | if (error) { | 1464 | if (error) { |
1457 | cancel_flags = 0; | 1465 | cancel_flags = 0; |
1458 | goto error_return; | 1466 | goto out_trans_cancel; |
1459 | } | 1467 | } |
1460 | 1468 | ||
1461 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); | 1469 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); |
1462 | unlock_dp_on_error = B_TRUE; | 1470 | unlock_dp_on_error = B_TRUE; |
1463 | 1471 | ||
1464 | xfs_bmap_init(&free_list, &first_block); | 1472 | /* |
1473 | * Check for directory link count overflow. | ||
1474 | */ | ||
1475 | if (is_dir && dp->i_d.di_nlink >= XFS_MAXLINK) { | ||
1476 | error = XFS_ERROR(EMLINK); | ||
1477 | goto out_trans_cancel; | ||
1478 | } | ||
1465 | 1479 | ||
1466 | ASSERT(ip == NULL); | 1480 | xfs_bmap_init(&free_list, &first_block); |
1467 | 1481 | ||
1468 | /* | 1482 | /* |
1469 | * Reserve disk quota and the inode. | 1483 | * Reserve disk quota and the inode. |
1470 | */ | 1484 | */ |
1471 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); | 1485 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); |
1472 | if (error) | 1486 | if (error) |
1473 | goto error_return; | 1487 | goto out_trans_cancel; |
1474 | 1488 | ||
1475 | error = xfs_dir_canenter(tp, dp, name, resblks); | 1489 | error = xfs_dir_canenter(tp, dp, name, resblks); |
1476 | if (error) | 1490 | if (error) |
1477 | goto error_return; | 1491 | goto out_trans_cancel; |
1478 | error = xfs_dir_ialloc(&tp, dp, mode, 1, | 1492 | |
1479 | rdev, credp, prid, resblks > 0, | 1493 | /* |
1480 | &ip, &committed); | 1494 | * A newly created regular or special file just has one directory |
1495 | * entry pointing to them, but a directory also the "." entry | ||
1496 | * pointing to itself. | ||
1497 | */ | ||
1498 | error = xfs_dir_ialloc(&tp, dp, mode, is_dir ? 2 : 1, rdev, credp, | ||
1499 | prid, resblks > 0, &ip, &committed); | ||
1481 | if (error) { | 1500 | if (error) { |
1482 | if (error == ENOSPC) | 1501 | if (error == ENOSPC) |
1483 | goto error_return; | 1502 | goto out_trans_cancel; |
1484 | goto abort_return; | 1503 | goto out_trans_abort; |
1485 | } | 1504 | } |
1486 | xfs_itrace_ref(ip); | ||
1487 | 1505 | ||
1488 | /* | 1506 | /* |
1489 | * At this point, we've gotten a newly allocated inode. | 1507 | * At this point, we've gotten a newly allocated inode. |
1490 | * It is locked (and joined to the transaction). | 1508 | * It is locked (and joined to the transaction). |
1491 | */ | 1509 | */ |
1492 | 1510 | xfs_itrace_ref(ip); | |
1493 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); | 1511 | ASSERT(xfs_isilocked(ip, XFS_ILOCK_EXCL)); |
1494 | 1512 | ||
1495 | /* | 1513 | /* |
@@ -1508,19 +1526,28 @@ xfs_create( | |||
1508 | resblks - XFS_IALLOC_SPACE_RES(mp) : 0); | 1526 | resblks - XFS_IALLOC_SPACE_RES(mp) : 0); |
1509 | if (error) { | 1527 | if (error) { |
1510 | ASSERT(error != ENOSPC); | 1528 | ASSERT(error != ENOSPC); |
1511 | goto abort_return; | 1529 | goto out_trans_abort; |
1512 | } | 1530 | } |
1513 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | 1531 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); |
1514 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); | 1532 | xfs_trans_log_inode(tp, dp, XFS_ILOG_CORE); |
1515 | 1533 | ||
1534 | if (is_dir) { | ||
1535 | error = xfs_dir_init(tp, ip, dp); | ||
1536 | if (error) | ||
1537 | goto out_bmap_cancel; | ||
1538 | |||
1539 | error = xfs_bumplink(tp, dp); | ||
1540 | if (error) | ||
1541 | goto out_bmap_cancel; | ||
1542 | } | ||
1543 | |||
1516 | /* | 1544 | /* |
1517 | * If this is a synchronous mount, make sure that the | 1545 | * If this is a synchronous mount, make sure that the |
1518 | * create transaction goes to disk before returning to | 1546 | * create transaction goes to disk before returning to |
1519 | * the user. | 1547 | * the user. |
1520 | */ | 1548 | */ |
1521 | if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) { | 1549 | if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) |
1522 | xfs_trans_set_sync(tp); | 1550 | xfs_trans_set_sync(tp); |
1523 | } | ||
1524 | 1551 | ||
1525 | /* | 1552 | /* |
1526 | * Attach the dquot(s) to the inodes and modify them incore. | 1553 | * Attach the dquot(s) to the inodes and modify them incore. |
@@ -1537,16 +1564,13 @@ xfs_create( | |||
1537 | IHOLD(ip); | 1564 | IHOLD(ip); |
1538 | 1565 | ||
1539 | error = xfs_bmap_finish(&tp, &free_list, &committed); | 1566 | error = xfs_bmap_finish(&tp, &free_list, &committed); |
1540 | if (error) { | 1567 | if (error) |
1541 | xfs_bmap_cancel(&free_list); | 1568 | goto out_abort_rele; |
1542 | goto abort_rele; | ||
1543 | } | ||
1544 | 1569 | ||
1545 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | 1570 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); |
1546 | if (error) { | 1571 | if (error) { |
1547 | IRELE(ip); | 1572 | IRELE(ip); |
1548 | tp = NULL; | 1573 | goto out_dqrele; |
1549 | goto error_return; | ||
1550 | } | 1574 | } |
1551 | 1575 | ||
1552 | XFS_QM_DQRELE(mp, udqp); | 1576 | XFS_QM_DQRELE(mp, udqp); |
@@ -1555,26 +1579,22 @@ xfs_create( | |||
1555 | *ipp = ip; | 1579 | *ipp = ip; |
1556 | 1580 | ||
1557 | /* Fallthrough to std_return with error = 0 */ | 1581 | /* Fallthrough to std_return with error = 0 */ |
1558 | 1582 | std_return: | |
1559 | std_return: | 1583 | if (DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { |
1560 | if ((*ipp || (error != 0 && dm_event_sent != 0)) && | 1584 | XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, dp, DM_RIGHT_NULL, |
1561 | DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { | 1585 | ip, DM_RIGHT_NULL, name->name, NULL, mode, |
1562 | (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, | 1586 | error, 0); |
1563 | dp, DM_RIGHT_NULL, | ||
1564 | *ipp ? ip : NULL, | ||
1565 | DM_RIGHT_NULL, name->name, NULL, | ||
1566 | mode, error, 0); | ||
1567 | } | 1587 | } |
1588 | |||
1568 | return error; | 1589 | return error; |
1569 | 1590 | ||
1570 | abort_return: | 1591 | out_bmap_cancel: |
1592 | xfs_bmap_cancel(&free_list); | ||
1593 | out_trans_abort: | ||
1571 | cancel_flags |= XFS_TRANS_ABORT; | 1594 | cancel_flags |= XFS_TRANS_ABORT; |
1572 | /* FALLTHROUGH */ | 1595 | out_trans_cancel: |
1573 | 1596 | xfs_trans_cancel(tp, cancel_flags); | |
1574 | error_return: | 1597 | out_dqrele: |
1575 | if (tp != NULL) | ||
1576 | xfs_trans_cancel(tp, cancel_flags); | ||
1577 | |||
1578 | XFS_QM_DQRELE(mp, udqp); | 1598 | XFS_QM_DQRELE(mp, udqp); |
1579 | XFS_QM_DQRELE(mp, gdqp); | 1599 | XFS_QM_DQRELE(mp, gdqp); |
1580 | 1600 | ||
@@ -1583,20 +1603,18 @@ std_return: | |||
1583 | 1603 | ||
1584 | goto std_return; | 1604 | goto std_return; |
1585 | 1605 | ||
1586 | abort_rele: | 1606 | out_abort_rele: |
1587 | /* | 1607 | /* |
1588 | * Wait until after the current transaction is aborted to | 1608 | * Wait until after the current transaction is aborted to |
1589 | * release the inode. This prevents recursive transactions | 1609 | * release the inode. This prevents recursive transactions |
1590 | * and deadlocks from xfs_inactive. | 1610 | * and deadlocks from xfs_inactive. |
1591 | */ | 1611 | */ |
1612 | xfs_bmap_cancel(&free_list); | ||
1592 | cancel_flags |= XFS_TRANS_ABORT; | 1613 | cancel_flags |= XFS_TRANS_ABORT; |
1593 | xfs_trans_cancel(tp, cancel_flags); | 1614 | xfs_trans_cancel(tp, cancel_flags); |
1594 | IRELE(ip); | 1615 | IRELE(ip); |
1595 | 1616 | unlock_dp_on_error = B_FALSE; | |
1596 | XFS_QM_DQRELE(mp, udqp); | 1617 | goto out_dqrele; |
1597 | XFS_QM_DQRELE(mp, gdqp); | ||
1598 | |||
1599 | goto std_return; | ||
1600 | } | 1618 | } |
1601 | 1619 | ||
1602 | #ifdef DEBUG | 1620 | #ifdef DEBUG |
@@ -2004,8 +2022,10 @@ xfs_link( | |||
2004 | /* Return through std_return after this point. */ | 2022 | /* Return through std_return after this point. */ |
2005 | 2023 | ||
2006 | error = XFS_QM_DQATTACH(mp, sip, 0); | 2024 | error = XFS_QM_DQATTACH(mp, sip, 0); |
2007 | if (!error && sip != tdp) | 2025 | if (error) |
2008 | error = XFS_QM_DQATTACH(mp, tdp, 0); | 2026 | goto std_return; |
2027 | |||
2028 | error = XFS_QM_DQATTACH(mp, tdp, 0); | ||
2009 | if (error) | 2029 | if (error) |
2010 | goto std_return; | 2030 | goto std_return; |
2011 | 2031 | ||
@@ -2110,209 +2130,6 @@ std_return: | |||
2110 | goto std_return; | 2130 | goto std_return; |
2111 | } | 2131 | } |
2112 | 2132 | ||
2113 | |||
2114 | int | ||
2115 | xfs_mkdir( | ||
2116 | xfs_inode_t *dp, | ||
2117 | struct xfs_name *dir_name, | ||
2118 | mode_t mode, | ||
2119 | xfs_inode_t **ipp, | ||
2120 | cred_t *credp) | ||
2121 | { | ||
2122 | xfs_mount_t *mp = dp->i_mount; | ||
2123 | xfs_inode_t *cdp; /* inode of created dir */ | ||
2124 | xfs_trans_t *tp; | ||
2125 | int cancel_flags; | ||
2126 | int error; | ||
2127 | int committed; | ||
2128 | xfs_bmap_free_t free_list; | ||
2129 | xfs_fsblock_t first_block; | ||
2130 | boolean_t unlock_dp_on_error = B_FALSE; | ||
2131 | boolean_t created = B_FALSE; | ||
2132 | int dm_event_sent = 0; | ||
2133 | xfs_prid_t prid; | ||
2134 | struct xfs_dquot *udqp, *gdqp; | ||
2135 | uint resblks; | ||
2136 | |||
2137 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
2138 | return XFS_ERROR(EIO); | ||
2139 | |||
2140 | tp = NULL; | ||
2141 | |||
2142 | if (DM_EVENT_ENABLED(dp, DM_EVENT_CREATE)) { | ||
2143 | error = XFS_SEND_NAMESP(mp, DM_EVENT_CREATE, | ||
2144 | dp, DM_RIGHT_NULL, NULL, | ||
2145 | DM_RIGHT_NULL, dir_name->name, NULL, | ||
2146 | mode, 0, 0); | ||
2147 | if (error) | ||
2148 | return error; | ||
2149 | dm_event_sent = 1; | ||
2150 | } | ||
2151 | |||
2152 | /* Return through std_return after this point. */ | ||
2153 | |||
2154 | xfs_itrace_entry(dp); | ||
2155 | |||
2156 | mp = dp->i_mount; | ||
2157 | udqp = gdqp = NULL; | ||
2158 | if (dp->i_d.di_flags & XFS_DIFLAG_PROJINHERIT) | ||
2159 | prid = dp->i_d.di_projid; | ||
2160 | else | ||
2161 | prid = (xfs_prid_t)dfltprid; | ||
2162 | |||
2163 | /* | ||
2164 | * Make sure that we have allocated dquot(s) on disk. | ||
2165 | */ | ||
2166 | error = XFS_QM_DQVOPALLOC(mp, dp, | ||
2167 | current_fsuid(), current_fsgid(), prid, | ||
2168 | XFS_QMOPT_QUOTALL | XFS_QMOPT_INHERIT, &udqp, &gdqp); | ||
2169 | if (error) | ||
2170 | goto std_return; | ||
2171 | |||
2172 | tp = xfs_trans_alloc(mp, XFS_TRANS_MKDIR); | ||
2173 | cancel_flags = XFS_TRANS_RELEASE_LOG_RES; | ||
2174 | resblks = XFS_MKDIR_SPACE_RES(mp, dir_name->len); | ||
2175 | error = xfs_trans_reserve(tp, resblks, XFS_MKDIR_LOG_RES(mp), 0, | ||
2176 | XFS_TRANS_PERM_LOG_RES, XFS_MKDIR_LOG_COUNT); | ||
2177 | if (error == ENOSPC) { | ||
2178 | resblks = 0; | ||
2179 | error = xfs_trans_reserve(tp, 0, XFS_MKDIR_LOG_RES(mp), 0, | ||
2180 | XFS_TRANS_PERM_LOG_RES, | ||
2181 | XFS_MKDIR_LOG_COUNT); | ||
2182 | } | ||
2183 | if (error) { | ||
2184 | cancel_flags = 0; | ||
2185 | goto error_return; | ||
2186 | } | ||
2187 | |||
2188 | xfs_ilock(dp, XFS_ILOCK_EXCL | XFS_ILOCK_PARENT); | ||
2189 | unlock_dp_on_error = B_TRUE; | ||
2190 | |||
2191 | /* | ||
2192 | * Check for directory link count overflow. | ||
2193 | */ | ||
2194 | if (dp->i_d.di_nlink >= XFS_MAXLINK) { | ||
2195 | error = XFS_ERROR(EMLINK); | ||
2196 | goto error_return; | ||
2197 | } | ||
2198 | |||
2199 | /* | ||
2200 | * Reserve disk quota and the inode. | ||
2201 | */ | ||
2202 | error = XFS_TRANS_RESERVE_QUOTA(mp, tp, udqp, gdqp, resblks, 1, 0); | ||
2203 | if (error) | ||
2204 | goto error_return; | ||
2205 | |||
2206 | error = xfs_dir_canenter(tp, dp, dir_name, resblks); | ||
2207 | if (error) | ||
2208 | goto error_return; | ||
2209 | /* | ||
2210 | * create the directory inode. | ||
2211 | */ | ||
2212 | error = xfs_dir_ialloc(&tp, dp, mode, 2, | ||
2213 | 0, credp, prid, resblks > 0, | ||
2214 | &cdp, NULL); | ||
2215 | if (error) { | ||
2216 | if (error == ENOSPC) | ||
2217 | goto error_return; | ||
2218 | goto abort_return; | ||
2219 | } | ||
2220 | xfs_itrace_ref(cdp); | ||
2221 | |||
2222 | /* | ||
2223 | * Now we add the directory inode to the transaction. | ||
2224 | * We waited until now since xfs_dir_ialloc might start | ||
2225 | * a new transaction. Had we joined the transaction | ||
2226 | * earlier, the locks might have gotten released. An error | ||
2227 | * from here on will result in the transaction cancel | ||
2228 | * unlocking dp so don't do it explicitly in the error path. | ||
2229 | */ | ||
2230 | IHOLD(dp); | ||
2231 | xfs_trans_ijoin(tp, dp, XFS_ILOCK_EXCL); | ||
2232 | unlock_dp_on_error = B_FALSE; | ||
2233 | |||
2234 | xfs_bmap_init(&free_list, &first_block); | ||
2235 | |||
2236 | error = xfs_dir_createname(tp, dp, dir_name, cdp->i_ino, | ||
2237 | &first_block, &free_list, resblks ? | ||
2238 | resblks - XFS_IALLOC_SPACE_RES(mp) : 0); | ||
2239 | if (error) { | ||
2240 | ASSERT(error != ENOSPC); | ||
2241 | goto error1; | ||
2242 | } | ||
2243 | xfs_ichgtime(dp, XFS_ICHGTIME_MOD | XFS_ICHGTIME_CHG); | ||
2244 | |||
2245 | error = xfs_dir_init(tp, cdp, dp); | ||
2246 | if (error) | ||
2247 | goto error2; | ||
2248 | |||
2249 | error = xfs_bumplink(tp, dp); | ||
2250 | if (error) | ||
2251 | goto error2; | ||
2252 | |||
2253 | created = B_TRUE; | ||
2254 | |||
2255 | *ipp = cdp; | ||
2256 | IHOLD(cdp); | ||
2257 | |||
2258 | /* | ||
2259 | * Attach the dquots to the new inode and modify the icount incore. | ||
2260 | */ | ||
2261 | XFS_QM_DQVOPCREATE(mp, tp, cdp, udqp, gdqp); | ||
2262 | |||
2263 | /* | ||
2264 | * If this is a synchronous mount, make sure that the | ||
2265 | * mkdir transaction goes to disk before returning to | ||
2266 | * the user. | ||
2267 | */ | ||
2268 | if (mp->m_flags & (XFS_MOUNT_WSYNC|XFS_MOUNT_DIRSYNC)) { | ||
2269 | xfs_trans_set_sync(tp); | ||
2270 | } | ||
2271 | |||
2272 | error = xfs_bmap_finish(&tp, &free_list, &committed); | ||
2273 | if (error) { | ||
2274 | IRELE(cdp); | ||
2275 | goto error2; | ||
2276 | } | ||
2277 | |||
2278 | error = xfs_trans_commit(tp, XFS_TRANS_RELEASE_LOG_RES); | ||
2279 | XFS_QM_DQRELE(mp, udqp); | ||
2280 | XFS_QM_DQRELE(mp, gdqp); | ||
2281 | if (error) { | ||
2282 | IRELE(cdp); | ||
2283 | } | ||
2284 | |||
2285 | /* Fall through to std_return with error = 0 or errno from | ||
2286 | * xfs_trans_commit. */ | ||
2287 | |||
2288 | std_return: | ||
2289 | if ((created || (error != 0 && dm_event_sent != 0)) && | ||
2290 | DM_EVENT_ENABLED(dp, DM_EVENT_POSTCREATE)) { | ||
2291 | (void) XFS_SEND_NAMESP(mp, DM_EVENT_POSTCREATE, | ||
2292 | dp, DM_RIGHT_NULL, | ||
2293 | created ? cdp : NULL, | ||
2294 | DM_RIGHT_NULL, | ||
2295 | dir_name->name, NULL, | ||
2296 | mode, error, 0); | ||
2297 | } | ||
2298 | return error; | ||
2299 | |||
2300 | error2: | ||
2301 | error1: | ||
2302 | xfs_bmap_cancel(&free_list); | ||
2303 | abort_return: | ||
2304 | cancel_flags |= XFS_TRANS_ABORT; | ||
2305 | error_return: | ||
2306 | xfs_trans_cancel(tp, cancel_flags); | ||
2307 | XFS_QM_DQRELE(mp, udqp); | ||
2308 | XFS_QM_DQRELE(mp, gdqp); | ||
2309 | |||
2310 | if (unlock_dp_on_error) | ||
2311 | xfs_iunlock(dp, XFS_ILOCK_EXCL); | ||
2312 | |||
2313 | goto std_return; | ||
2314 | } | ||
2315 | |||
2316 | int | 2133 | int |
2317 | xfs_symlink( | 2134 | xfs_symlink( |
2318 | xfs_inode_t *dp, | 2135 | xfs_inode_t *dp, |
@@ -2587,51 +2404,6 @@ std_return: | |||
2587 | } | 2404 | } |
2588 | 2405 | ||
2589 | int | 2406 | int |
2590 | xfs_inode_flush( | ||
2591 | xfs_inode_t *ip, | ||
2592 | int flags) | ||
2593 | { | ||
2594 | xfs_mount_t *mp = ip->i_mount; | ||
2595 | int error = 0; | ||
2596 | |||
2597 | if (XFS_FORCED_SHUTDOWN(mp)) | ||
2598 | return XFS_ERROR(EIO); | ||
2599 | |||
2600 | /* | ||
2601 | * Bypass inodes which have already been cleaned by | ||
2602 | * the inode flush clustering code inside xfs_iflush | ||
2603 | */ | ||
2604 | if (xfs_inode_clean(ip)) | ||
2605 | return 0; | ||
2606 | |||
2607 | /* | ||
2608 | * We make this non-blocking if the inode is contended, | ||
2609 | * return EAGAIN to indicate to the caller that they | ||
2610 | * did not succeed. This prevents the flush path from | ||
2611 | * blocking on inodes inside another operation right | ||
2612 | * now, they get caught later by xfs_sync. | ||
2613 | */ | ||
2614 | if (flags & FLUSH_SYNC) { | ||
2615 | xfs_ilock(ip, XFS_ILOCK_SHARED); | ||
2616 | xfs_iflock(ip); | ||
2617 | } else if (xfs_ilock_nowait(ip, XFS_ILOCK_SHARED)) { | ||
2618 | if (xfs_ipincount(ip) || !xfs_iflock_nowait(ip)) { | ||
2619 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
2620 | return EAGAIN; | ||
2621 | } | ||
2622 | } else { | ||
2623 | return EAGAIN; | ||
2624 | } | ||
2625 | |||
2626 | error = xfs_iflush(ip, (flags & FLUSH_SYNC) ? XFS_IFLUSH_SYNC | ||
2627 | : XFS_IFLUSH_ASYNC_NOBLOCK); | ||
2628 | xfs_iunlock(ip, XFS_ILOCK_SHARED); | ||
2629 | |||
2630 | return error; | ||
2631 | } | ||
2632 | |||
2633 | |||
2634 | int | ||
2635 | xfs_set_dmattrs( | 2407 | xfs_set_dmattrs( |
2636 | xfs_inode_t *ip, | 2408 | xfs_inode_t *ip, |
2637 | u_int evmask, | 2409 | u_int evmask, |
@@ -2676,7 +2448,7 @@ xfs_reclaim( | |||
2676 | ASSERT(!VN_MAPPED(VFS_I(ip))); | 2448 | ASSERT(!VN_MAPPED(VFS_I(ip))); |
2677 | 2449 | ||
2678 | /* bad inode, get out here ASAP */ | 2450 | /* bad inode, get out here ASAP */ |
2679 | if (VN_BAD(VFS_I(ip))) { | 2451 | if (is_bad_inode(VFS_I(ip))) { |
2680 | xfs_ireclaim(ip); | 2452 | xfs_ireclaim(ip); |
2681 | return 0; | 2453 | return 0; |
2682 | } | 2454 | } |
@@ -3090,7 +2862,7 @@ xfs_free_file_space( | |||
3090 | 2862 | ||
3091 | /* | 2863 | /* |
3092 | * Need to zero the stuff we're not freeing, on disk. | 2864 | * Need to zero the stuff we're not freeing, on disk. |
3093 | * If its a realtime file & can't use unwritten extents then we | 2865 | * If it's a realtime file & can't use unwritten extents then we |
3094 | * actually need to zero the extent edges. Otherwise xfs_bunmapi | 2866 | * actually need to zero the extent edges. Otherwise xfs_bunmapi |
3095 | * will take care of it for us. | 2867 | * will take care of it for us. |
3096 | */ | 2868 | */ |
diff --git a/fs/xfs/xfs_vnodeops.h b/fs/xfs/xfs_vnodeops.h index 76df328c61b4..04373c6c61ff 100644 --- a/fs/xfs/xfs_vnodeops.h +++ b/fs/xfs/xfs_vnodeops.h | |||
@@ -31,14 +31,11 @@ int xfs_remove(struct xfs_inode *dp, struct xfs_name *name, | |||
31 | struct xfs_inode *ip); | 31 | struct xfs_inode *ip); |
32 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, | 32 | int xfs_link(struct xfs_inode *tdp, struct xfs_inode *sip, |
33 | struct xfs_name *target_name); | 33 | struct xfs_name *target_name); |
34 | int xfs_mkdir(struct xfs_inode *dp, struct xfs_name *dir_name, | ||
35 | mode_t mode, struct xfs_inode **ipp, cred_t *credp); | ||
36 | int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize, | 34 | int xfs_readdir(struct xfs_inode *dp, void *dirent, size_t bufsize, |
37 | xfs_off_t *offset, filldir_t filldir); | 35 | xfs_off_t *offset, filldir_t filldir); |
38 | int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, | 36 | int xfs_symlink(struct xfs_inode *dp, struct xfs_name *link_name, |
39 | const char *target_path, mode_t mode, struct xfs_inode **ipp, | 37 | const char *target_path, mode_t mode, struct xfs_inode **ipp, |
40 | cred_t *credp); | 38 | cred_t *credp); |
41 | int xfs_inode_flush(struct xfs_inode *ip, int flags); | ||
42 | int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); | 39 | int xfs_set_dmattrs(struct xfs_inode *ip, u_int evmask, u_int16_t state); |
43 | int xfs_reclaim(struct xfs_inode *ip); | 40 | int xfs_reclaim(struct xfs_inode *ip); |
44 | int xfs_change_file_space(struct xfs_inode *ip, int cmd, | 41 | int xfs_change_file_space(struct xfs_inode *ip, int cmd, |