summaryrefslogtreecommitdiffstats
path: root/fs
diff options
context:
space:
mode:
authorEric Biggers <ebiggers@google.com>2017-03-31 18:31:48 +0100
committerAl Viro <viro@zeniv.linux.org.uk>2017-04-03 01:05:57 -0400
commit64bd72048a2ac07efed70debe606a1c6e5e03554 (patch)
tree1666d9e34b9a4a47ed54ab9eceabf4f56d6dc39a /fs
parentb15fb70b82299f92bb8d591c9d1731cb23fa8290 (diff)
statx: optimize copy of struct statx to userspace
I found that statx() was significantly slower than stat(). As a microbenchmark, I compared 10,000,000 invocations of fstat() on a tmpfs file to the same with statx() passed a NULL path: $ time ./stat_benchmark real 0m1.464s user 0m0.275s sys 0m1.187s $ time ./statx_benchmark real 0m5.530s user 0m0.281s sys 0m5.247s statx is expected to be a little slower than stat because struct statx is larger than struct stat, but not by *that* much. It turns out that most of the overhead was in copying struct statx to userspace, mostly in all the stac/clac instructions that got generated for each __put_user() call. (This was on x86_64, but some other architectures, e.g. arm64, have something similar now too.) stat() instead initializes its struct on the stack and copies it to userspace with a single call to copy_to_user(). This turns out to be much faster, and changing statx to do this makes it almost as fast as stat: $ time ./statx_benchmark real 0m1.624s user 0m0.270s sys 0m1.354s For zeroing the reserved fields, start by zeroing the full struct with memset. This makes it clear that every byte copied to userspace is initialized, even implicit padding bytes (though there are none currently). In the scenarios I tested, it also performed the same as a designated initializer. Manually initializing each field was still slightly faster, but would have been more error-prone and less verifiable. Also rename statx_set_result() to cp_statx() for consistency with cp_old_stat() et al., and make it noinline so that struct statx doesn't add to the stack usage during the main portion of the syscall execution. Signed-off-by: Eric Biggers <ebiggers@google.com> Signed-off-by: David Howells <dhowells@redhat.com> Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Diffstat (limited to 'fs')
-rw-r--r--fs/stat.c74
1 files changed, 32 insertions, 42 deletions
diff --git a/fs/stat.c b/fs/stat.c
index b792dd201c31..ab27f2868588 100644
--- a/fs/stat.c
+++ b/fs/stat.c
@@ -510,46 +510,37 @@ SYSCALL_DEFINE4(fstatat64, int, dfd, const char __user *, filename,
}
#endif /* __ARCH_WANT_STAT64 || __ARCH_WANT_COMPAT_STAT64 */
-static inline int __put_timestamp(struct timespec *kts,
- struct statx_timestamp __user *uts)
+static noinline_for_stack int
+cp_statx(const struct kstat *stat, struct statx __user *buffer)
{
- return (__put_user(kts->tv_sec, &uts->tv_sec ) ||
- __put_user(kts->tv_nsec, &uts->tv_nsec ) ||
- __put_user(0, &uts->__reserved ));
-}
-
-/*
- * Set the statx results.
- */
-static long statx_set_result(struct kstat *stat, struct statx __user *buffer)
-{
- uid_t uid = from_kuid_munged(current_user_ns(), stat->uid);
- gid_t gid = from_kgid_munged(current_user_ns(), stat->gid);
-
- if (__put_user(stat->result_mask, &buffer->stx_mask ) ||
- __put_user(stat->mode, &buffer->stx_mode ) ||
- __clear_user(&buffer->__spare0, sizeof(buffer->__spare0)) ||
- __put_user(stat->nlink, &buffer->stx_nlink ) ||
- __put_user(uid, &buffer->stx_uid ) ||
- __put_user(gid, &buffer->stx_gid ) ||
- __put_user(stat->attributes, &buffer->stx_attributes ) ||
- __put_user(stat->blksize, &buffer->stx_blksize ) ||
- __put_user(MAJOR(stat->rdev), &buffer->stx_rdev_major ) ||
- __put_user(MINOR(stat->rdev), &buffer->stx_rdev_minor ) ||
- __put_user(MAJOR(stat->dev), &buffer->stx_dev_major ) ||
- __put_user(MINOR(stat->dev), &buffer->stx_dev_minor ) ||
- __put_timestamp(&stat->atime, &buffer->stx_atime ) ||
- __put_timestamp(&stat->btime, &buffer->stx_btime ) ||
- __put_timestamp(&stat->ctime, &buffer->stx_ctime ) ||
- __put_timestamp(&stat->mtime, &buffer->stx_mtime ) ||
- __put_user(stat->ino, &buffer->stx_ino ) ||
- __put_user(stat->size, &buffer->stx_size ) ||
- __put_user(stat->blocks, &buffer->stx_blocks ) ||
- __clear_user(&buffer->__spare1, sizeof(buffer->__spare1)) ||
- __clear_user(&buffer->__spare2, sizeof(buffer->__spare2)))
- return -EFAULT;
-
- return 0;
+ struct statx tmp;
+
+ memset(&tmp, 0, sizeof(tmp));
+
+ tmp.stx_mask = stat->result_mask;
+ tmp.stx_blksize = stat->blksize;
+ tmp.stx_attributes = stat->attributes;
+ tmp.stx_nlink = stat->nlink;
+ tmp.stx_uid = from_kuid_munged(current_user_ns(), stat->uid);
+ tmp.stx_gid = from_kgid_munged(current_user_ns(), stat->gid);
+ tmp.stx_mode = stat->mode;
+ tmp.stx_ino = stat->ino;
+ tmp.stx_size = stat->size;
+ tmp.stx_blocks = stat->blocks;
+ tmp.stx_atime.tv_sec = stat->atime.tv_sec;
+ tmp.stx_atime.tv_nsec = stat->atime.tv_nsec;
+ tmp.stx_btime.tv_sec = stat->btime.tv_sec;
+ tmp.stx_btime.tv_nsec = stat->btime.tv_nsec;
+ tmp.stx_ctime.tv_sec = stat->ctime.tv_sec;
+ tmp.stx_ctime.tv_nsec = stat->ctime.tv_nsec;
+ tmp.stx_mtime.tv_sec = stat->mtime.tv_sec;
+ tmp.stx_mtime.tv_nsec = stat->mtime.tv_nsec;
+ tmp.stx_rdev_major = MAJOR(stat->rdev);
+ tmp.stx_rdev_minor = MINOR(stat->rdev);
+ tmp.stx_dev_major = MAJOR(stat->dev);
+ tmp.stx_dev_minor = MINOR(stat->dev);
+
+ return copy_to_user(buffer, &tmp, sizeof(tmp)) ? -EFAULT : 0;
}
/**
@@ -573,8 +564,6 @@ SYSCALL_DEFINE5(statx,
if ((flags & AT_STATX_SYNC_TYPE) == AT_STATX_SYNC_TYPE)
return -EINVAL;
- if (!access_ok(VERIFY_WRITE, buffer, sizeof(*buffer)))
- return -EFAULT;
if (filename)
error = vfs_statx(dfd, filename, flags, &stat, mask);
@@ -582,7 +571,8 @@ SYSCALL_DEFINE5(statx,
error = vfs_statx_fd(dfd, &stat, mask, flags);
if (error)
return error;
- return statx_set_result(&stat, buffer);
+
+ return cp_statx(&stat, buffer);
}
/* Caller is here responsible for sufficient locking (ie. inode->i_lock) */
a id='n125' href='#n125'>125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274
{ "translations": {
    "Details" : "Ayrıntılar",
    "All contacts" : "Tüm kişiler",
    "Contacts" : "Kişiler",
    "A contacts app for Nextcloud" : "Nextcloud kişiler uygulaması",
    "The Nextcloud contacts app is a user interface for Nextcloud's CardDAV server. Easily sync contacts from various devices with your Nextcloud and edit them online.\n\n* 🚀 **Integration with other Nextcloud apps!** Currently Mail and Calendar – more to come.\n* 🎉 **Never forget a birthday!** You can sync birthdays and other recurring events with your Nextcloud Calendar.\n* 👥 **Sharing of Adressbooks!** You want to share your contacts with your friends or coworkers? No problem!\n* 🙈 **We’re not reinventing the wheel!** Based on the great and open SabreDAV library." : "Kişiler uygulaması Nextcloud Card DAV sunucusunun ara yüzüdür. Çeşitli aygıtlar üzerindeki kişileri kolayca Nextcloud hesabınız ile eşitler ve çevrimiçi olarak düzenlemenizi sağlar.\n\n* 🚀 **Diğer Nextcloud uygulamaları ile bütünleşiktir!** Şu anda Takvim, diğerleri yolda.\n* 🎉 **Doğum günlerini unutmayın!** Doğum günü ve diğer yinelenen etkinlikleri Nextcloud takviminiz üzerinden izleyebilirsiniz.\n* 👥 **Adres defterlerini paylaşma!** Kişilerinizi arkadaşlarınız ve iş arkadaşlarınız ile paylaşmak isterseniz sorun değil!\n* 🙈 **Tekerleği yeniden keşfetmiyoruz!** Harika açık SabreDAV kitaplığını kullanıyoruz.",
    "Copy to full name" : "Tam ada kopyala",
    "Omit year" : "Yıl dikkate alınmasın",
    "Allow updating avatars from social media" : "Avatarlar sosyal ağ üzerinden güncellenebilsin",
    "Please select a circle" : "Lütfen bir çevre seçin",
    "Loading circle …" : "Çevre yükleniyor …",
    "Your request to join this circle is pending approval" : "Bu çevreye girme isteğiniz onaylanmayı bekliyor",
    "You are not a member of {circle}" : "{circle} çevresinin üyesi değilsiniz ",
    "There was an error fetching the member list" : "Üye listesi alınırken bir sorun çıktı",
    "Loading contacts …" : "Kişiler yükleniyor…",
    "There are no contacts yet" : "Henüz bir kişi kaydı yok",
    "Create contact" : "Kişi ekle",
    "There are no contacts in this group" : "Bu grupta henüz bir kişi yok",
    "Create contacts" : "Kişiler ekle",
    "Add contacts" : "Kişileri ekle",
    "Loading …" : "Yükleniyor …",
    "Add member" : "Üye ekle",
    "Leave circle" : "Çevreden çık",
    "Delete circle" : "Çevreyi sil",
    "Download" : "İndir",
    "Send email" : "E-posta gönder",
    "Groups" : "Gruplar",
    "Create a new group" : "Yeni bir grup ekle",
    "Group name" : "Grup adı",
    "Circles" : "Çevreler",
    "Create a new circle" : "Yeni bir çevre ekle",
    "Contacts settings" : "Kişiler ayarları",
    "Show all groups" : "Tüm grupları görüntüle",
    "Collapse groups" : "Grupları daralt",
    "Show all circles" : "Tüm çevreleri görüntüle",
    "Collapse circles" : "Çevreleri daralt",
    "This group already exists" : "Bu grup zaten var",
    "This circle already exists" : "Bu çevre zaten var",
    "An error happened during the creation of the circle" : "Çevre eklenirken bir sorun çıktı",
    "Rename" : "Yeniden adlandır",
    "Enabled" : "Etkin",
    "Delete" : "Sil",
    "Copied" : "Kopyalandı",
    "Cannot copy" : "Kopyalanamadı",
    "Copy link" : "Bağlantıyı kopyala",
    "Toggling of address book was not successful" : "Adres defteri değiştirilemedi",
    "This will delete the address book and every contacts within it" : "Bu işlem adres defterini ve içindeki tüm kişileri siler",
    "Delete {addressbook}?" : "{addressbook} silinsin mi?",
    "Deletion of address book was not successful." : "Adres defteri silinemedi.",
    "Renaming of address book was not successful." : "Adres defteri yeniden adlandırılamadı.",
    "_Shared with {num} entity_::_Shared with {num} entities_" : ["{num} varlık ile paylaşılmış","{num} varlık ile paylaşılmış"],
    "Share with users or groups" : "Kullanıcı ve gruplarla paylaş",
    "No users or groups" : "Herhangi bir kullanıcı ya da grup yok",
    "can edit" : "düzenleyebilir",
    "Unable to delete the share" : "Paylaşım silinemedi",
    "Unable to change permissions" : "İzinler değiştirilemedi",
    "Import contacts" : "Kişileri içe aktar",
    "Import into the {addressbookName} address book" : "{addressbookName} adres defteri içine aktar",
    "Select local file" : "Yerel dosyayı seçin",
    "Import from Files" : "Dosyalar uygulamasından içe aktar",
    "Importing is disabled because there are no address books available" : "Kullanılabilecek bir adres defteri bulunamadığından içe aktarım devre dışı bırakıldı",
    "Choose a vCard file to import" : "İçe aktarılacak vCard dosyasını seçin",
    "Add new address book" : "Adres defteri ekle",
    "An error occurred, unable to create the address book" : "Bir sorun çıktı, adres defteri oluşturulamadı",
    "First name" : "Ad",
    "Last name" : "Soyad",
    "Phonetic first name" : "Fonetik ad",
    "Phonetic last name" : "Fonetik soyad",
    "Display name" : "Görüntülenecek ad",
    "Last modified" : "Son değişiklik",
    "Sort by {sorting}" : "{sorting} alanına göre sırala",
    "Update avatars from social media" : "Avatarlar sosyal ağ üzerinden güncellensin",
    "(refreshed once per week)" : "(haftada bir yenilenir)",
    "Address books" : "Adres defterleri",
    "An error happened during the config change" : "Yapılandırma değiştirilirken bir sorun çıktı",
    "Password protection" : "Parola koruması",
    "Enforce password protection on files shared to this circle" : "Bu çevreyle paylaşılan dosyalara parola koruması uygulansın",
    "Unique password …" : "Benzersiz parola…",
    "Save" : "Kaydet",
    "Change unique password" : "Benzersiz parolayı değiştir",
    "Failed to save password. Please try again later." : "Parola kaydedilemedi. Lütfen bir süre sonra yeniden deneyin.",
    "Circle name" : "Çevre adı",
    "Circle owned by {owner}" : "Sahibi {owner} olan çevreler ",
    "Request to join" : "Katılma isteğinde bulun",
    "Description" : "Açıklama",
    "There is no description for this circle" : "Bu çevre için bir açıklama yok",
    "Enter a description for the circle" : "Çevre için bir açıklama yazın",
    "An error happened during description sync" : "Açıklama eşitlenirken bir sorun çıktı",
    "An error happened during name sync" : "Ad eşitlenirken bir sorun çıktı",
    "Add new property" : "Özellik ekle",
    "Choose property type" : "Özellik türünü seçin",
    "Upload a new picture" : "Görsel yükle",
    "Choose from Files" : "Dosyalardan seçin",
    "Get from " : "Şuradan alınsın",
    "Download picture" : "Görseli indir",
    "Delete picture" : "Görseli sil",
    "Invalid image" : "Görsel geçersiz",
    "Image is too big (max 1MB)." : "Görsel çok büyük (en fazla 1MB).",
    "Pick an avatar" : "Bir avatar seçin",
    "Error while processing the picture." : "Görsel işlenirken sorun çıktı.",
    "Avatar downloaded from social network" : "Avatar sosyal ağ üzerinden indirildi",
    "Avatar already up to date" : "Avatar zaten güncel",
    "Avatar download failed" : "Avatar indirilemedi",
    "No contact selected" : "Herhangi bir kişi seçilmemiş",
    "Select a contact on the list to begin" : "Başlamak için listeden bir kişi seçin",
    "Name" : "Ad",
    "Company" : "Kuruluş",
    "Title" : "Unvan",
    "This contact was broken and received a fix. Please review the content and click here to save it." : "Bu kişinin bilgileri hatalıydı ve bir düzeltme yapıldı. Lütfen içeriği gözden geçirip kaydetmek için buraya tıklayın.",
    "Clone contact" : "Kişiyi kopyala",
    "Generate QR Code" : "QR kodu üret",
    "Contact vCard as QR code" : "QRkod olarak sanal kişi kartı",
    "Pick an address book" : "Bir adres defteri seçin",
    "Select address book" : "Adres defterini seçin",
    "Cancel" : "İptal",
    "This contact is not yet synced. Edit it to save it to the server." : "Bu kişi henüz eşitlenmemiş. Sunucuya kaydetmek için düzenleyin.",
    "This contact is in read-only mode. You do not have permission to edit this contact." : "Bu kişi salt okunur kipte olduğundan kişiyi düzenleme izniniz yok.",
    "The contact you were trying to edit has changed. Please manually refresh the contact. Any further edits will be discarded." : "Düzenlemeye çalıştığınız kişi değiştirilmiş. Lütfen kişiyi el ile yenileyin. Bundan sonra yapılacak düzenlemeler yok sayılacak.",
    "Address book" : "Adres defteri",
    "New contact" : "Yeni kişi",
    "Syntax error. Cannot open the contact." : "Yazım hatası. Kişi bulunamadı.",
    "The contact doesn't exists anymore on the server." : "Kişi artık sunucu üzerinde değil.",
    "Unable to retrieve the contact from the server, please check your network connection." : "Kişi sunucudan alınamadı. Lütfen ağ bağlantınızı denetleyin.",
    "An error occurred while trying to move the contact" : "Kişi taşınırken bir sorun çıktı",
    "An error occurred while trying to copy the contact" : "Kişi kopyalanırken bir sorun çıktı",
    "Search contacts …" : "Kişi arama…",
    "Add to {group}" : "{group} grubuna ekle",
    "Remove {type}" : "{type} sil",
    "Search {types}" : "{types} arama",
    "Search for people to add" : "Eklenecek kişileri arayın",
    "No results" : "Herhangi bir sonuç bulunamadı",
    "Add to group" : "Gruba ekle",
    "Add {type}" : "{type} ekle",
    "New circle name" : "Yeni çevre adı",
    "Personal circle" : "Kişisel çevre",
    "This circle will only be visible to you. Other members will not be able to see or use it." : "Bu çevreyi yalnızca siz görebilirsiniz. Diğer üyeler bu çevreyi göremez ya da kullanamaz.",
    "Local circle" : "Yerel çevre",
    "This circle will not be shared with the other instances of the global scale" : "Bu çevre küresel ölçekte diğer kopyalar ile paylaşılamaz",
    "Create circle" : "Çevre ekle",
    "Loading members list …" : "Üye listesi ekleniyor …",
    "The list of members is only visible to members of this circle" : "Üye listesi yalnızca bu çevredeki üyeler tarafından görülebilir",
    "There is no member in this circle" : "Bu çevrenin henüz bir üyesi yok ",
    "Add members" : "Üye ekle",
    "Show circle details" : "Çevre ayrıntılarını görüntüle",
    "Add to {circle}" : "{circle} çevresine ekle",
    "Unable to get the recommendations list" : "Öneriler listesi alınamadı",
    "Unable to get the results" : "Sonuçlar alınamadı",
    "Some members could not be added" : "Bazı üyeler eklenemedi",
    "There was an issue adding members to the circle" : "Üyeler çevreye eklenirken bir sorun çıktı",
    "Accept membership request" : "Üyelik isteğini kabul et",
    "Reject membership request" : "Üyelik isteğini reddet",
    "Manage level" : "Düzeyi değiştir",
    "Remove member" : "Üyeyi sil",
    "Pending" : "Bekleyen",
    "Promote as sole owner" : "Sahip olarak ata",
    "Promote to {level}" : "{level} düzeyine yükselt",
    "Demote to {level}" : "{level} düzeyine düşür",
    "Could not delete the member {displayName}" : "{displayName} üyesi silinemedi",
    "Could not change the member level to {level}"